Checkbox

Used in forms when a user needs to select multiple values from several options

Usage

import { Checkbox } from "chakra-ui-solid";
<Checkbox.Root>
  <Checkbox.HiddenInput />
  <Checkbox.Control>
    <Checkbox.Indicator />
  </Checkbox.Control>
  <Checkbox.Label />
</Checkbox.Root>

Checkbox.Root renders the <label> and Checkbox.HiddenInput renders the real <input type="checkbox"> inside it, so a click anywhere in the row toggles the box. The input is not optional — without it there is nothing focusable, nothing to submit, and nothing for the label to point at.

If you prefer a closed component composition, check out the snippet below.

Shortcuts

The Checkbox component also provides a set of shortcuts for common use cases.

CheckboxControl

This component renders the Checkbox.Indicator within it by default.

This works:

<Checkbox.Control>
  <Checkbox.Indicator />
</Checkbox.Control>

This might be more concise, if you don’t need to customize the indicator:

<Checkbox.Control />

Examples

Variants

Pass the variant prop to the Checkbox.Root component to change the visual style of the checkbox.

outline

subtle

solid

Colors

Pass the colorPalette prop to the Checkbox.Root component to change the color of the checkbox.

gray

red

green

blue

teal

pink

purple

cyan

orange

yellow

Sizes

Pass the size prop to the Checkbox.Root component to change the size of the checkbox.

States

Pass the disabled or invalid prop to the Checkbox.Root component to change the visual state of the checkbox.

Controlled

Use the checked and onCheckedChange props to control the state of the checkbox.

Label Position

Here’s an example of how to change the label position to the right.

Store

An alternative way to control the checkbox is to use the RootProvider component and the createCheckbox store hook.

This way you can access the checkbox state and methods from outside the checkbox.

checked: false

Composition

Here’s an example of how to compose a checkbox with a field component.

Form Validation

Here’s an example of a checkbox driven by a signal, with a validation message on submit.

Checked: false

Group

Use the CheckboxGroup component to group multiple checkboxes together.

Select framework

Group Validation

The same, for a group: the ticked values are one array, and the message hangs off the fieldset.

Select your framework
Values: []

Custom Icon

Render a custom icon within Checkbox.Control to change the icon of the checkbox.

To replace the mark for one state only, pass checked or indeterminate to Checkbox.Indicator. Each is a function handed the indicator’s computed props, so spread them onto your glyph — Merging the computed class is what to read if your own class has to survive that spread.

Indeterminate

Set the checked prop to indeterminate to show the checkbox in an indeterminate state.

Description

Here’s an example of how to add some further description to the checkbox.

Render an anchor tag within the Checkbox.Label to add a link to the label.

Closed Component

Here’s how to setup the Checkbox for a closed component composition.

Guides

CheckboxGroup + Field vs Fieldset

When working with multiple checkboxes, it’s important to understand the semantic difference between Field and Fieldset:

  • Single Checkbox: Wrap with Field.Root for proper form field structure with labels and helper text
  • CheckboxGroup: Wrap with Fieldset.Root, not Field.Root

A checkbox group represents a collection of related options and should be marked up as a fieldset with a legend, not as a single field. Wrapping CheckboxGroup in Field.Root can cause interaction issues where only the first checkbox responds to clicks.

✅ Correct Usage:

<Fieldset.Root>
  <CheckboxGroup name="framework">
    <Fieldset.Legend>Select framework</Fieldset.Legend>
    {/* ... checkboxes ... */}
  </CheckboxGroup>
</Fieldset.Root>

❌ Incorrect Usage:

// Don't wrap CheckboxGroup with Field.Root
<Field.Root>
  <CheckboxGroup>{/* ... checkboxes ... */}</CheckboxGroup>
</Field.Root>

Styling the box

The whole checkmark — the border, the radius, the fill and the size — is on the control slot, not on Checkbox.Indicator. Style Checkbox.Control to change how the box looks; the indicator only carries the glyph inside it.

<Checkbox.Control borderRadius="full" />

Props

Root

CheckboxRootProps
PropDefaultType
checked—
checkbox.CheckedState

The controlled checked state. Pass `undefined` for uncontrolled.

defaultChecked—
checkbox.CheckedState

The state a fresh, uncontrolled checkbox starts in.

disabled—
boolean

Whether the checkbox can be toggled or focused at all. Inherited from a surrounding Field.

form—
string

The id of a form elsewhere on the page that this checkbox submits with.

id—
string

Seeds every id the machine hands out — the root is `checkbox:{id}`, the hidden input `checkbox:{id}:input`. Defaults to a generated id, and **does not become the root element's own `id`**: pass `ids` to control the attributes themselves.

ids—
CheckboxElementIds

Override individual element ids, for pointing an ARIA relationship at a specific one.

invalid—
boolean

Whether the checkbox shows its error treatment. Inherited from a surrounding Field.

name—
string

The hidden input's `name`, for form submission.

onCheckedChange—
(details: CheckboxCheckedChangeDetails) => void

Called whenever the checked state changes, from either side.

readOnly—
boolean

Whether the checkbox refuses to change while staying focusable. Inherited from a Field.

required—
boolean

Whether the form requires this box to be ticked. Inherited from a surrounding Field.

size'md'
ConditionalValue<'xs' | 'sm' | 'md' | 'lg' | PresetVariant<'checkbox', 'size'>>

The box's size, its gap to the label, and the label's text style.

value'on'
string

The hidden input's `value`, for form submission — and the key a `<CheckboxGroup>` tracks this box by.

variant'solid'
ConditionalValue<'outline' | 'solid' | 'subtle' | PresetVariant<'checkbox', 'variant'>>

How the box is painted once it is ticked.

Plus Omit<HTMLChakraProps<"label">, "id"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

RootProvider

CheckboxRootProviderProps
PropDefaultType
size'md'
ConditionalValue<'xs' | 'sm' | 'md' | 'lg' | PresetVariant<'checkbox', 'size'>>

The box's size, its gap to the label, and the label's text style.

value*—
CreateCheckboxReturn

A machine built by {@link createCheckbox}, so the consumer owns it rather than the Root.

variant'solid'
ConditionalValue<'outline' | 'solid' | 'subtle' | PresetVariant<'checkbox', 'variant'>>

How the box is painted once it is ticked.

Plus HTMLChakraProps<"label"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Indicator

CheckboxIndicatorProps
PropDefaultType
checked—
RenderProp<ComponentProps<'svg'>>

Draws instead of the tick while the box is checked.

indeterminate—
RenderProp<ComponentProps<'svg'>>

Draws instead of the dash while the box is indeterminate.

Plus HTMLChakraProps<"svg"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.

Group

CheckboxGroupProps
PropDefaultType
defaultValue—
string[]

The values ticked in a fresh, uncontrolled group.

disabled—
boolean

Disables every checkbox in the group. Inherited from a surrounding Fieldset.

invalid—
boolean

Marks every checkbox in the group invalid. Inherited from a surrounding Fieldset.

maxSelectedValues—
number

How many boxes may be ticked at once — the unticked ones disable themselves at the ceiling.

name—
string

The `name` every checkbox in the group submits under.

onValueChange—
(value: string[]) => void

Called with the whole new set whenever any box in the group changes.

readOnly—
boolean

Makes every checkbox in the group read-only.

value—
string[]

The controlled set of ticked values. Pass `undefined` for uncontrolled.

Plus HTMLChakraProps<"div"> — the whole style-prop surface and the DOM attributes of the element it renders, several hundred names listed as their sources rather than expanded — and the three every component takes: as, render and unstyled.