XDSCheckboxInput@xds/core · CheckboxInput

Usage

CheckboxInput toggles a single on/off value. Use it for settings like "Enable notifications", terms acceptance, or opt-in choices. For multiple checkboxes in a group, use CheckboxList instead.

Best practices

GuidancePractices
DoAlways provide a visible label so the user knows what they are toggling. Use isLabelHidden only when surrounding context makes it obvious.
DoAdd a description for choices that need extra context, like explaining what "Share usage data" actually shares.
DoUse the indeterminate state for "select all" checkboxes when only some items in a group are selected.
Don'tUse a checkbox for mutually exclusive choices — use RadioList when only one option can be selected.
Don'tUse a checkbox for actions that take effect immediately — use a toggle switch or button instead.

Anatomy

ElementDescription
CheckboxrequiredThe check box itself — unchecked, checked, or indeterminate.
LabelrequiredText describing what the checkbox controls. Always present for accessibility.
DescriptionHelper text below the label with additional context.
Status messageAn error, warning, or success message below the checkbox.

Import

ts
import {XDSCheckboxInput} from '@xds/core/CheckboxInput'

Props

PropTypeDescription
labelrequired
stringLabel text for the checkbox (always rendered for accessibility).
valuerequired
boolean | 'indeterminate'Whether the checkbox is checked, unchecked, or indeterminate.
ref
React.Ref<HTMLInputElement>Ref forwarded to the underlying <input> element.
isLabelHidden
boolean (default: false)Whether to visually hide the label (still accessible to screen readers).
description
stringDescription text displayed below the label.
onChange
(checked: boolean, e: ChangeEvent<HTMLInputElement>) => voidCallback fired when the checkbox state changes.
changeAction
(checked: boolean, e: ChangeEvent<HTMLInputElement>) => void | Promise<void>Async action on change. Fires after onChange if not prevented. Shows loading spinner while pending.
isLoading
boolean (default: false)Whether the checkbox is in a loading state. Shows spinner and prevents interaction.
isDisabled
boolean (default: false)Whether the checkbox is disabled.
isOptional
boolean (default: false)Whether the field is optional. Mutually exclusive with isRequired.
isRequired
boolean (default: false)Whether the checkbox is required. Mutually exclusive with isOptional.
size
'sm' | 'md' (default: 'md')The size of the checkbox. sm for compact layouts, md for default.
onFocus
(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the checkbox receives focus.
onBlur
(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the checkbox loses focus.
labelIcon
XDSIconTypeIcon to display before the label text. See `npx xds docs icons` for valid semantic names.
status
{ type: 'error' | 'warning' | 'success', message: string }Status indicator. Displays a colored message box below the checkbox and sets aria-invalid for errors.

Examples

Common configurations, variations, and states.
CheckboxInput — IndeterminateA
tsx
'use client';
import {useState} from 'react';
import {XDSCheckboxInput} from '@xds/core/CheckboxInput';
import {XDSStack} from '@xds/core/Layout';
import {XDSDivider} from '@xds/core/Divider';
export default function CheckboxInputIndeterminateState() {
const [items, setItems] = useState({
email: true,
push: false,
sms: true,
slack: false,
});
const checkedCount = Object.values(items).filter(Boolean).length;
const totalCount = Object.keys(items).length;
const selectAllValue =
checkedCount === 0
? false
: checkedCount === totalCount
? true
: ('indeterminate' as const);
const handleSelectAll = (checked: boolean) => {
setItems({email: checked, push: checked, sms: checked, slack: checked});
};
return (
<XDSStack direction="vertical" gap={3}>
<XDSCheckboxInput
label="Select all notifications"
description={`${checkedCount} of ${totalCount} enabled`}
value={selectAllValue}
onChange={handleSelectAll}
/>
<XDSDivider />
<XDSStack direction="vertical" gap={3}>
<XDSCheckboxInput
label="Email notifications"
value={items.email}
onChange={v => setItems(prev => ({...prev, email: v}))}
/>
<XDSCheckboxInput
label="Push notifications"
value={items.push}
onChange={v => setItems(prev => ({...prev, push: v}))}
/>
<XDSCheckboxInput
label="SMS alerts"
value={items.sms}
onChange={v => setItems(prev => ({...prev, sms: v}))}
/>
<XDSCheckboxInput
label="Slack messages"
value={items.slack}
onChange={v => setItems(prev => ({...prev, slack: v}))}
/>
</XDSStack>
</XDSStack>
);
}
CheckboxInput — StatesCheckboxes with labels and descriptions in checked, unchecked, and disabled states. Each checkbox controls a single on/off setting. Add a description to explain what the setting does.
tsx
'use client';
import {useState} from 'react';
import {XDSCheckboxInput} from '@xds/core/CheckboxInput';
import {XDSStack} from '@xds/core/Layout';
export default function CheckboxInputBasic() {
const [checked, setChecked] = useState<boolean | 'indeterminate'>(true);
const [unchecked, setUnchecked] = useState<boolean | 'indeterminate'>(false);
const [disabled, setDisabled] = useState<boolean | 'indeterminate'>(false);
const [indeterminate, setIndeterminate] = useState<boolean | 'indeterminate'>(
'indeterminate',
);
return (
<XDSStack direction="vertical" gap={4}>
<XDSCheckboxInput
label="Checked"
description="This checkbox is currently on."
value={checked}
onChange={setChecked}
/>
<XDSCheckboxInput
label="Unchecked"
description="This checkbox is currently off."
value={unchecked}
onChange={setUnchecked}
/>
<XDSCheckboxInput
label="Disabled"
description="This checkbox cannot be changed."
value={disabled}
onChange={setDisabled}
isDisabled
/>
<XDSCheckboxInput
label="Indeterminate"
description="This checkbox represents a partial selection."
value={indeterminate}
onChange={setIndeterminate}
/>
</XDSStack>
);
}
CheckboxInput — StatusCheckboxes with error, warning, and success validation messages. Use the status prop to show feedback after form validation — errors block submission, warnings inform, and success confirms.
tsx
'use client';
import {useState} from 'react';
import {XDSCheckboxInput} from '@xds/core/CheckboxInput';
import {XDSStack} from '@xds/core/Layout';
export default function CheckboxInputStatusVariations() {
const [error, setError] = useState<boolean | 'indeterminate'>(false);
const [warning, setWarning] = useState<boolean | 'indeterminate'>(true);
const [success, setSuccess] = useState<boolean | 'indeterminate'>(true);
return (
<XDSStack direction="vertical" gap={4}>
<XDSCheckboxInput
label="Error"
description="Required field that has not been accepted."
value={error}
onChange={setError}
status={{
type: 'error',
message: 'You must accept the terms to continue',
}}
/>
<XDSCheckboxInput
label="Warning"
description="Enabled setting with a side effect to be aware of."
value={warning}
onChange={setWarning}
status={{
type: 'warning',
message: 'This data may be shared with partners',
}}
/>
<XDSCheckboxInput
label="Success"
description="Confirmed setting that has been verified."
value={success}
onChange={setSuccess}
status={{type: 'success', message: 'Your email has been verified'}}
/>
</XDSStack>
);
}

Showcase source

tsx
'use client';
import {useState} from 'react';
import {XDSCheckboxInput} from '@xds/core/CheckboxInput';
import {XDSStack} from '@xds/core/Layout';
export default function CheckboxInputShowcase() {
const [notifications, setNotifications] = useState(true);
const [marketing, setMarketing] = useState(false);
return (
<XDSStack direction="vertical" gap={2}>
<XDSCheckboxInput
label="Checked"
value={notifications}
onChange={setNotifications}
/>
<XDSCheckboxInput
label="Unchecked"
value={marketing}
onChange={setMarketing}
/>
</XDSStack>
);
}