# Checkbox URL: https://ark-ui.com/docs/components/checkbox Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/checkbox.mdx A control element that allows for multiple selections within a set. --- ## Anatomy ```tsx ``` ## Examples **Example: basic** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import { Check } from 'lucide-ripple'; import styles from 'styles/checkbox.module.css'; export component Basic() { {'Checkbox'} } ``` ### Default Checked Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally. **Example: default-checked** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component DefaultChecked() { {'Checkbox'} } ``` ### Controlled Use the `checked` and `onCheckedChange` props to programatically control the checkbox's state. **Example: controlled** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { track } from 'ripple'; import { Check } from 'lucide-ripple'; export component Controlled() { let checked = track(true); { @checked = e.checked; }} > {'Checkbox'} } ``` ### Root Provider An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** ```ripple import { Checkbox, useCheckbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import button from 'styles/button.module.css'; import { Check } from 'lucide-ripple'; export component RootProvider() { const checkbox = useCheckbox();
{'Checkbox'} if (@checkbox.checked) { } else { }
} ``` ### Disabled Use the `disabled` prop to make the checkbox non-interactive. **Example: disabled** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component Disabled() { {'Checkbox'} } ``` ### Indeterminate Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked). **Example: indeterminate** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check, Minus } from 'lucide-ripple'; export component Indeterminate() { {'Checkbox'} } ``` ### Field The checkbox integrates smoothly with the `Field` component to handle form state, helper text, and error text for proper accessibility. **Example: with-field** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import { Field } from 'ark-ripple/field'; import { Check, Minus } from 'lucide-ripple'; import styles from 'styles/checkbox.module.css'; import field from 'styles/field.module.css'; export component WithField() { {'Label'} {'Additional Info'} {'Error Info'} } ``` ### Form Pass the `name` and `value` props to the `Checkbox.Root` component to make the checkbox part of a form. The checkbox's value will be submitted with the form when the user submits it. **Example: with-form** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import button from 'styles/button.module.css'; import { Check } from 'lucide-ripple'; export component WithForm() {
{ e.preventDefault(); console.log('terms:', new FormData(e.currentTarget).get('terms')); }} > {'I agree to the terms and conditions'}
} ``` ### Context Access the checkbox's state and methods with `Checkbox.Context` or the `useCheckboxContext` hook. **Example: context** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component Context() { component children({ context }) { {'Checked: '} {String(@context.checked)} } } ``` ## Checkbox Group Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values. ```tsx ``` **Example: group** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component Group() { for (const item of items; key item.value) { {item.label} } } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Controlled Use the `value` and `onValueChange` props to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection. **Example: group-controlled** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { track } from 'ripple'; import { Check } from 'lucide-ripple'; export component GroupControlled() { let value = track(['react']);
{'value: '} {JSON.stringify(@value)} { @value = v; console.log(v); }} > for (const item of items; key item.value) { {item.label} }
} const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Root Provider Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes. **Example: group-provider** ```ripple import { Checkbox, useCheckboxGroup } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component GroupProvider() { const group = useCheckboxGroup( { defaultValue: ['react'], name: 'framework', }, ); for (const item of items; key item.value) { {item.label} } } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Invalid Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group. **Example: group-with-invalid** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component GroupWithInvalid() { for (const item of items; key item.value) { {item.label} } } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Max Selected Use the `maxSelectedValues` prop to limit the number of checkboxes that can be selected at once. Once the maximum is reached, remaining checkboxes become disabled. **Example: group-with-max-selected** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import { Check } from 'lucide-ripple'; export component GroupWithMaxSelected() { for (const item of items; key item.value) { {item.label} } } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ]; ``` ### Select All Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected. **Example: group-with-select-all** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import { Check, Minus } from 'lucide-ripple'; import { track, trackSplit } from 'ripple'; import styles from 'styles/checkbox.module.css'; component CheckboxItem(props: Checkbox.RootProps & { children?: any }) { } export component GroupWithSelectAll() { let value = track([]); const handleSelectAll = (checked: boolean) => { @value = checked ? items.map((item) => item.value) : []; }; const allSelected = track(() => @value.length === items.length); const indeterminate = track(() => @value.length > 0 && @value.length < items.length);
{'Selected: '} {JSON.stringify(@value)} { handleSelectAll(!!e.checked); }} > {'JSX Frameworks'} { @value = v; }} > for (const item of items; key item.value) { {item.label} }
} const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Form Use the `Checkbox.Group` component within a form to handle multiple checkbox values with form submission. The `name` prop ensures all selected values are collected as an array when the form is submitted using `FormData.getAll()`. **Example: group-with-form** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import styles from 'styles/checkbox.module.css'; import button from 'styles/button.module.css'; import { Check } from 'lucide-ripple'; export component GroupWithForm() {
{ e.preventDefault(); console.log(new FormData(e.currentTarget).getAll('framework')); }} > for (const item of items; key item.value) { {item.label} }
} const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ### Fieldset Use the `Fieldset` component with `Checkbox.Group` to provide semantic grouping with legend, helper text, and error text support. **Example: group-with-fieldset** ```ripple import { Checkbox } from 'ark-ripple/checkbox'; import { Fieldset } from 'ark-ripple/fieldset'; import { Check } from 'lucide-ripple'; import styles from 'styles/checkbox.module.css'; import fieldset from 'styles/fieldset.module.css'; export component GroupWithFieldset() { {'Select frameworks'} {'Choose your preferred frameworks'} for (const item of items; key item.value) { {item.label} } } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ]; ``` ## Guides ### asChild Behavior The `Checkbox.Root` element of the checkbox is a `label` element. This is because the checkbox is a form control and should be associated with a label to provide context and meaning to the user. Otherwise, the HTML and accessibility structure will be invalid. > If you need to use the `asChild` property, make sure that the `label` element is the direct child of the > `Checkbox.Root` component. ## API Reference ### Props **Component API Reference** **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `maxSelectedValues` | `number` | No | The maximum number of selected values | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `checked` | `boolean` | Whether the checkbox is checked | | `disabled` | `boolean` | Whether the checkbox is disabled | | `indeterminate` | `boolean` | Whether the checkbox is indeterminate | | `focused` | `boolean` | Whether the checkbox is focused | | `checkedState` | `CheckedState` | The checked state of the checkbox | | `setChecked` | `(checked: CheckedState) => void` | Function to set the checked state of the checkbox | | `toggleChecked` | `VoidFunction` | Function to toggle the checked state of the checkbox | ## Accessibility Complies with the [Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). ### Keyboard Support