QCheckbox component
Requirements
Type | Path / Version | Purpose | Optional |
---|---|---|---|
Styles | ../../assets/main.css | CSS Variables | No |
Functions | ../../use/uuid | Assign ids to items | No |
Usage
Import the following component/s:
import QCheckbox from '../../components/Form/QCheckbox.vue'
Basic usage
In the most basic case, you can bind a dynamic boolean value to v-model
.
Example
<template>
<form @submit.prevent="onSubmit">
<q-checkbox v-model="inputValue" label="I have read the terms and conditions" />
<p>Output: {{inputValue}}</p>
</form>
</template>
<script setup>
import { ref } from 'vue';
const inputValue = ref(false);
</script>
Display a switch element
The variant="switch"
binding makes the checkbox look like a switch.
Example
<template>
<form @submit.prevent="onSubmit">
<q-checkbox variant="switch" v-model="inputValue" label="I have read the terms and conditions" />
<p>Output: {{inputValue}}</p>
</form>
</template>
<script setup>
import { ref } from 'vue';
const inputValue = ref(false);
</script>
Required fields
See QInput@required-fields for behavior and customization
Example
<template>
<form @submit.prevent="onSubmit">
<q-checkbox required requiredSign="[Please agree]" v-model="inputValue" label="I have read the terms and conditions " />
<p>Output: {{ inputValue }}</p>
<q-button type="submit" label="Submit" />
</form>
</template>
<script setup>
import { ref } from 'vue';
const inputValue = ref(false);
</script>
Full component's code
QCheckbox
<template>
<input
type="checkbox"
class="q-input-base"
:class="{
'q-error': !!error,
'q-input-switch': variant === 'switch',
}"
v-bind="$attrs"
@change="$emit('update:modelValue', $event.target.checked)"
:checked="modelValue"
:id="id"
:required="required"
:aria-label="label"
:aria-required="required"
:aria-checked="modelValue"
:aria-describedby="error ? `${id}-error` : null"
:aria-invalid="error ? true : null"
/>
<label
v-if="label"
:for="id"
class="q-input-label"
:class="{
'q-input-label-switch': variant === 'switch',
}"
>
<!-- Switch variant hides the input and replaces it with a custom element -->
<span v-if="variant === 'switch'" class="q-switch" :class="{ 'q-switch-active': modelValue }">
<div class="q-switch-toggle" :class="{ 'q-switch-toggle-checked': modelValue }"></div>
</span>
<!-- /Switch variant -->
<span :class="{ 'q-input-label-flex': variant === 'switch' }" v-html="label"></span>
</label>
<span class="q-input-required-sign" v-if="required">{{ requiredSign }}</span>
</template>
<script setup>
import uuid from "../../use/uuid";
const id = uuid();
defineProps({
label: {
type: String,
default: "",
},
modelValue: {
type: Boolean,
default: false,
},
variant: {
type: String,
default: "checkbox",
validator(value) {
return value === "checkbox" || value === "switch";
},
},
error: {
type: String,
default: "",
},
required: {
type: Boolean,
default: false,
},
requiredSign: {
type: String,
default: "*",
},
});
</script>
<style scoped>
.q-input-base,
.q-input-label {
font-size: var(--text-size-sm);
}
.q-input-label {
color: var(--accent-color-primary);
font-size: var(--text-size-sm);
font-weight: 600;
}
.q-input-required-sign {
color: var(--color-error);
}
.q-input-base {
background-color: transparent;
color: var(--text-color-primary);
caret-color: var(--text-color-primary);
border: none;
border-bottom: var(--gap-xxs) solid transparent;
padding: var(--gap-sm) var(--gap-xs);
margin: var(--gap-sm);
}
.q-input-base:focus {
outline: none;
transition: var(--duration-quickest);
border-bottom: var(--gap-xxs) solid var(--accent-color-primary);
}
.q-input-base:focus.q-error {
border-bottom: var(--gap-xxs) solid var(--color-error);
}
.q-input-error-msg {
font-size: var(--text-xs);
color: var(--color-error);
}
/* Style for switch toggle */
.q-input-switch {
display: none;
}
.q-switch {
transition: all var(--duration-quick);
background: var(--text-color-primary);
border: calc(var(--el-size-xxs) * 0.025) solid var(--black-color);
border-radius: var(--el-size-xxs);
cursor: pointer;
height: calc(var(--el-size-xxs) * 0.5);
position: relative;
padding: calc(var(--el-size-xxs) * 0.1);
width: var(--el-size-xxs);
z-index: 1;
opacity: var(--opacity-disabled);
margin-right: var(--gap-sm);
}
.q-switch-active {
transition: all var(--duration-quick);
opacity: var(--opacity-enabled);
}
.q-switch .q-switch-toggle {
position: absolute;
background-color: var(--accent-color-primary);
border-radius: 50%;
top: calc(var(--el-size-xxs) * 0.05);
left: calc(var(--el-size-xxs) * 0.1);
height: calc(var(--el-size-xxs) * 0.35);
width: calc(var(--el-size-xxs) * 0.35);
transform: translateX(0);
transition: transform 0.3s ease, background-color 0.5s ease;
}
.q-input-label-switch {
display: flex;
}
.q-switch-toggle-checked {
transform: translateX(calc(var(--el-size-xxs) * 0.4)) !important;
}
</style>