import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Text,
} from '@vega-ui/react';
<div>
<Checkbox style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<CheckboxInput defaultChecked />- Browser support
- Widely available
- Chrome 111
- Edge 111
- Firefox 121
- Safari 15.4
- Safari on iOS 15.4
- Bundle size
- :has()
- Oklab and OkLCh — comes from the design tokens
- clip-path
- :focus-visible
- :where()
Summary
Checkbox is a compound component for independent selectable options, with optional native form participation, indicator rendering, and indeterminate state support. It is the selection-family primitive for independent or combinable choices rather than immediate setting toggles.
Imports
import {
Checkbox,
CheckboxInput,
CheckboxIndicator,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
type CheckboxProps,
type CheckboxSize,
type CheckboxVariant,
} from '@vega-ui/react';Exported Types
CheckboxPropsCheckboxInputPropsCheckboxIndicatorPropsCheckboxCheckedIconPropsCheckboxIndeterminateIconPropsCheckboxSizeCheckboxVariant
Minimal Composition
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
} from '@vega-ui/react';
export default function MinimalComposition() {
return (
<Checkbox style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-4)' }}>
<CheckboxInput name='remember' />Required Parts
Checkbox: root state and label surfaceCheckboxInput: the native checkbox — focus, keyboard, state and form valueCheckboxIndicator: visible checkbox surface
Optional Parts
CheckboxCheckedIcon: checked-state iconCheckboxIndeterminateIcon: indeterminate-state icon
Composition Order
CheckboxCheckboxInputCheckboxIndicatorCheckboxCheckedIconCheckboxIndeterminateIcon- label text
Variants
- Sizes:
sm,md,lg - Variants:
primary,secondary - States: unchecked, checked, indeterminate, disabled
Edge Cases
- Give
CheckboxInputanamefor native form submission. - Indeterminate usually represents partial selection rather than a third final value.
- Keep indicator and text inside one unified clickable row.
- If the control represents one immediate system setting,
Switchis usually clearer than a checkbox row.
Common Mistakes
- Leaving out
CheckboxInput, which is the actual control. - Treating indeterminate as a final persisted state by default.
- Using checkbox UI for mutually exclusive options.
Examples
Basic
Basic: group of independent options
A Fieldset with a legend groups several independent choices. Each Checkbox is the <label> itself, so the text inside it is the accessible name and the whole row is clickable. Every input shares one name and carries its own value.
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Fieldset,
FieldsetLegend,
} from '@vega-ui/react';
const options = [
{ value: 'mentions', label: 'Someone mentions me in a comment', checked: true },Controlled/Stateful
Controlled/Stateful: parent with indeterminate state
The parent checkbox is derived from the children: checked when all permissions are granted, indeterminate when only some are. Clicking it selects or clears the whole group, and the counter below reads the same state.
import { useState } from 'react';
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Text,
} from '@vega-ui/react';
const permissions = ['View invoices', 'Download invoices', 'Edit payment methods', 'Cancel subscription'];
Form/Integration
Form/Integration: reading values with FormData
Checked inputs with the same name submit as repeated entries, so FormData.getAll('topics') returns every selected value. A single checkbox submits its value only when checked; an unchecked one is absent from the form data. The reset button restores defaultChecked.
import { FormEvent, useState } from 'react';
import {
Button,
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Fieldset,
FieldsetLegend,
Text,
} from '@vega-ui/react';Layout/Overlay
Layout/Overlay: filter list inside a drawer
The checkboxes live in a form method='dialog' inside a Drawer: submitting reads FormData, applies the filters and closes the drawer. The trigger shows how many filters are applied, and reopening the drawer starts from the applied values.
import { CSSProperties, FormEvent, useState } from 'react';
import {
Button,
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Drawer,
DrawerClose,
DrawerContent,
DrawerTrigger,Layout/Overlay: row selection in a table
Checkboxes in table cells have no visible text, so each CheckboxInput gets an aria-label naming its row. The header checkbox selects all rows and turns indeterminate on partial selection; the toolbar action reacts to the selection.
import { useState } from 'react';
import {
Button,
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Table,
TableBody,
TableData,
TableHead,Error
Error: required agreement
The input is natively required. Its invalid event replaces the browser bubble with a HelperText linked through aria-describedby and sets aria-invalid; checking the box clears the error.
import { FormEvent, useState } from 'react';
import {
Button,
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
HelperText,
} from '@vega-ui/react';
export default function RequiredAgreementCheckbox() {Disabled
Disabled: disabled by a fieldset
While “Use workspace defaults” is checked, the Fieldset is disabled and every checkbox inside inherits it natively. The security alerts option is always disabled and explains why through aria-describedby. Disabled inputs are not submitted with the form.
import { useState } from 'react';
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Fieldset,
FieldsetLegend,
HelperText,
} from '@vega-ui/react';
Edge
Edge: long labels in a narrow column
Long text wraps under itself while the indicator stays at the first line: align the row to flex-start and give CheckboxIndicator flex-shrink: 0, otherwise flex squeezes the box. Unbroken strings such as email addresses need overflow-wrap: anywhere.
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
} from '@vega-ui/react';
export default function LongLabelWrapping() {
return (
<div style={{ display: 'grid', gap: 'var(--spacing-8)', width: '100%' }}>
<Checkbox style={{ display: 'flex', alignItems: 'flex-start', gap: 'var(--spacing-4)' }}>Edge: hundreds of options with select all
240 options in a scrollable group, with a Set of selected values so toggling stays cheap. The select-all checkbox derives checked and indeterminate from the set size.
import { useState } from 'react';
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
Text,
} from '@vega-ui/react';
const teams = ['billing', 'search', 'auth', 'checkout', 'payments', 'catalog', 'inventory', 'shipping', 'reviews', 'ads', 'email', 'reports'];
const services = ['api', 'worker', 'web', 'gateway', 'scheduler'];Anatomy
Overview
Checkbox is a compound component that coordinates checked, indeterminate, disabled, and form-participation behavior across a root label and exported visual parts.
Required Parts
Checkbox
Required. Owns size, variant, checked, indeterminate, and disabled state.
CheckboxIndicator
Required for the visible control surface.
CheckboxInput
Required. The visually hidden native checkbox: focus, keyboard, checked state and form value come from it. Without it the indicator is an empty, unfocusable box.
Optional Parts
CheckboxCheckedIcon
Optional checked-state icon inside the indicator.
CheckboxIndeterminateIcon
Optional indeterminate-state icon inside the indicator.
Composition Order
CheckboxCheckboxInputCheckboxIndicatorCheckboxCheckedIconCheckboxIndeterminateIcon- label text
Valid Composition Patterns
Two valid shapes: text inside the Checkbox root, which is the <label> and gives the input its name, and a bare checkbox (for example in a table cell) whose CheckboxInput gets an aria-label. CheckboxIndeterminateIcon can be left out when the checkbox never becomes indeterminate.
import {
Checkbox,
CheckboxCheckedIcon,
CheckboxIndeterminateIcon,
CheckboxIndicator,
CheckboxInput,
} from '@vega-ui/react';
export default function ValidCompositionPatterns() {
return (
<div style={{ display: 'grid', gap: 'var(--spacing-8)' }}>
<Checkbox style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-4)' }}>Invalid Composition Patterns
Visual indicator without CheckboxInput
This leaves no focusable control and breaks native form participation.
Indeterminate used as a final persisted state by accident
Indeterminate is usually a visual partial-selection state, not a separate business value.
Split label and indicator as separate click targets
The root label should keep the control and text together as one interaction row.