<script setup lang="ts">
import { CheckboxIndicator, CheckboxRoot } from 'akar';
import { ref } from 'vue';
import './styles.css';
const checkboxOne = ref(true);
</script>
<template>
<div class="akar-demo akar-demo-Checkbox">
<div :style="{ display: 'flex', alignItems: 'center' }">
<label>
<CheckboxRoot
v-model="checkboxOne"
class="CheckboxRoot"
>
<CheckboxIndicator class="CheckboxIndicator">
<PIcon name="i-lucide-check" />
</CheckboxIndicator>
</CheckboxRoot>
<span class="Label">Accept terms and conditions.</span>
</label>
</div>
</div>
</template>@import '../_colors/black-alpha.css';
@import '../_colors/grass.css';
@scope (.akar-demo-Checkbox) {
/* reset */
button {
all: unset;
}
.CheckboxRoot {
background-color: white;
width: 25px;
height: 25px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 10px var(--black-a7);
}
.CheckboxRoot:hover {
background-color: var(--grass-3);
}
.CheckboxRoot:focus {
box-shadow: 0 0 0 2px black;
}
.CheckboxIndicator {
color: var(--grass-11);
}
.Label {
color: white;
padding-left: 15px;
font-size: 15px;
line-height: 1;
}
}Features
- Supports indeterminate state.
- Full keyboard navigation.
- Can be controlled or uncontrolled.
- Supports custom true/false values.
Installation
Install the component from your command line.
pnpm add akar
yarn add akar
npm install akar
bun add akar
Anatomy
Import all parts and piece them together.
<script setup>
import { CheckboxGroupRoot, CheckboxIndicator, CheckboxRoot } from 'akar';
</script>
<template>
<CheckboxRoot>
<CheckboxIndicator />
</CheckboxRoot>
<!-- or with array support -->
<CheckboxGroupRoot>
<CheckboxRoot>
<CheckboxIndicator />
</CheckboxRoot>
</CheckboxGroupRoot>
</template>
API Reference
Root
Contains all the parts of a checkbox. An input will also render when used within a form to ensure events propagate correctly.
| Prop | Default | Type |
|---|---|---|
as | "button" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultValue | T | "indeterminate"The value of the checkbox when it is initially rendered. Use when you do not need to control its value. | |
disabled | booleanWhen | |
falseValue | (() => false) as unknown as undefined | TThe value used when the checkbox is unchecked. Defaults to |
id | stringId of the element | |
modelValue | null | T | "indeterminate"The controlled value of the checkbox. Can be binded with v-model. | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
required | booleanWhen | |
trueValue | (() => true) as unknown as undefined | TThe value used when the checkbox is checked. Defaults to |
value | "on" | AcceptableValueThe value given as data when submitted with a |
| Event | Payload |
|---|---|
update:modelValue | value: T | "indeterminate"Event handler called when the value of the checkbox changes. |
| Slot (default) | Payload |
|---|---|
modelValue | T | "indeterminate"Current value |
state | false | true | "indeterminate"Current state |
| Data attribute | Value |
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" |
[data-disabled] | Present when disabled |
Indicator
Renders when the checkbox is in a checked or indeterminate state. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.
| Prop | Default | Type |
|---|---|---|
as | "span" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
| Data attribute | Value |
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" |
[data-disabled] | Present when disabled |
Group Root
Wrapper around CheckboxRoot to support array of modelValue
| Prop | Default | Type |
|---|---|---|
as | "div" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultValue | T[]The value of the checkbox when it is initially rendered. Use when you do not need to control its value. | |
dir | "ltr" | "rtl"The direction of navigation between items. | |
disabled | booleanWhen | |
loop | false | booleanWhether keyboard navigation should loop around |
max | number | nullThe maximum number of values that can be selected. Once reached, the unchecked
checkboxes get | |
modelValue | T[]The controlled value of the checkbox. Can be binded with v-model. | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
orientation | "vertical" | "horizontal"The orientation of the group. Mainly so arrow navigation is done accordingly (left & right vs. up & down) | |
required | booleanWhen | |
rovingFocus | true | booleanWhen |
| Event | Payload |
|---|---|
update:modelValue | value: T[]Event handler called when the value of the checkbox changes. |
Examples
Custom Values
Use the trueValue and falseValue props to specify custom values for the checked and unchecked states instead of the default true/false.
<script setup>
import { Icon } from '@iconify/vue'
import { CheckboxIndicator, CheckboxRoot } from 'akar'
import { ref } from 'vue'
// With string values
const acceptTerms = ref('no')
// With number values
const permission = ref(0)
</script>
<template>
<!-- String values -->
<CheckboxRoot v-model="acceptTerms" true-value="yes" false-value="no">
<CheckboxIndicator>
<Icon icon="radix-icons:check" />
</CheckboxIndicator>
</CheckboxRoot>
Value: {{ acceptTerms }} <!-- "yes" or "no" -->
<!-- Number values -->
<CheckboxRoot v-model="permission" :true-value="1" :false-value="0">
<CheckboxIndicator>
<Icon icon="radix-icons:check" />
</CheckboxIndicator>
</CheckboxRoot>
Value: {{ permission }} <!-- 1 or 0 -->
</template>
Indeterminate
You can set the checkbox to indeterminate by taking control of its state.
<script setup>
import { Icon } from '@iconify/vue'
import { CheckboxIndicator, CheckboxRoot } from 'akar'
const checked = ref('indeterminate')
</script>
<template>
<CheckboxRoot v-model="checked">
<CheckboxIndicator>
<Icon
v-if="checked === 'indeterminate'"
icon="radix-icons:divider-horizontal"
/>
<Icon
v-if="checked"
icon="radix-icons:check"
/>
</CheckboxIndicator>
</CheckboxRoot>
<button
type="button"
@click="() => (checked === 'indeterminate' ? (checked = false) : (checked = 'indeterminate'))"
>
Toggle indeterminate
</button>
</template>
Accessibility
Adheres to the tri-state Checkbox WAI-ARIA design pattern.
Keyboard Interactions
| Key | Description |
|---|---|
| Space | Checks/unchecks the checkbox |