Checkbox
Checkboxes allow users to select multiple items from a list of individual items, or to mark one individual item as selected.
Updated in eds-core: 1.12.0
Quick Start
- Installation
npm install @adaptavant/eds-core
- Import
import { Checkbox } from '@adaptavant/eds-core';
Size
Customise the size of the Checkbox via the size
prop.
{/* large */}
<Checkbox label="Check me!" size="large" />
{/* standard */}
<Checkbox label="Check me!" size="standard" />
Disabled
Use the isDisabled
prop to show that a Checkbox isn't usable.
Invalid
Use the errorMessage
prop to show that a Checkbox has an error associated with it.
Controlled
A controlled Checkbox component uses React’s state and a callback function to update the state.
const [selected, setSelected] = React.useState(false);
const handleChange = (e) => setSelected(e.target.checked);
return (
<Stack>
<Checkbox label="Check me!" onChange={handleChange} />
<Text className="text-body-12"> Status: {selected ? "Checked ✅ " : "Unchecked ❌"}</Text>
</Stack>
);
Uncontrolled
An uncontrolled Checkbox component uses ref
prop to access the current selected state. Additionally, you can maintain a React state to update other UI elements if needed.
const checkboxRef = React.useRef(null);
const [selected, setSelected] = React.useState(true);
const handleChange = () => {
if (checkboxRef.current) {
setSelected(checkboxRef.current.checked);
}
};
const handleClick = () => {
alert(`My value is: "${checkboxRef.current.checked}"`);
};
return (
<Stack className="gap-2">
<Checkbox defaultChecked={true} label="Check me!" onChange={handleChange} ref={checkboxRef} />
<Text className="text-body-12"> Status: {selected ? "Checked ✅ " : "Unchecked ❌"} </Text>
<Button onClick={handleClick}>Click me!</Button>
</Stack>
);
Indeterminate
The Checkbox component includes an indeterminate
prop, designed for scenarios like header groups where some, but not all, options are selected. This is particularly useful for select-all checkboxes in group headers, as it visually indicates a partially selected state when only a subset of items is checked.
const [checkedItems, setCheckedItems] = React.useState({
1: true, // By default checked (makes header checkbox render in indeterminate state)
2: false,
3: false,
4: false,
});
const [headerDisabled, setHeaderDisabled] = React.useState(false); // toggle this to make header checkbox disabled
const disabledItems = {
1: false,
2: true, // By default disabled checkbox sub-item
3: false,
4: false,
};
const enabledItems = Object.keys(checkedItems).filter(
(key) => !disabledItems[key]
);
const allChecked = enabledItems.every((key) => checkedItems[key]);
const someChecked = enabledItems.some((key) => checkedItems[key]) && !allChecked;
const handleHeaderChange = () => {
const newCheckedState = !allChecked;
setCheckedItems((prevState) => {
const updatedState = { ...prevState };
enabledItems.forEach((key) => {
updatedState[key] = newCheckedState;
});
return updatedState;
});
};
const handleItemChange = (id) => {
setCheckedItems((prevState) => ({
...prevState,
[id]: !prevState[id],
}));
};
return (
<Stack className="gap-2">
<Checkbox
checked={allChecked}
isDisabled={headerDisabled}
indeterminate={someChecked} // Visually indicates a partially selected state
label="Select all"
onChange={handleHeaderChange}
/>
<Stack className="pl-5">
<Checkbox
checked={checkedItems['1']}
id="1"
isDisabled={headerDisabled || disabledItems['1']} // When header is disabled, all sub-items should disabled
label="Item 1"
onChange={() => handleItemChange('1')}
/>
<Checkbox
checked={checkedItems['2']}
id="2"
isDisabled={headerDisabled || disabledItems['2']} // By default disabled (header checkbox should not consider this for allchecked/somechecked state)
label="Item 2"
onChange={() => handleItemChange('2')}
/>
<Checkbox
checked={checkedItems['3']}
id="3"
isDisabled={headerDisabled || disabledItems['3']}
label="Item 3"
onChange={() => handleItemChange('3')} // Ensure "id" is passed to handleItemChange
/>
<Checkbox
checked={checkedItems['4']}
id="4"
isDisabled={headerDisabled || disabledItems['3']}
label="Item 4"
onChange={() => handleItemChange('4')}
/>
</Stack>
</Stack>
);
Note: This is purely a visual change. It has no impact on whether the checkbox's value is used in a form submission. That is decided by the checked state, regardless of the indeterminate state.
Style API
Our design system components include style props that allow you to easily customize different parts of each component to match your design needs.
Please refer to the Style API documentation for more insights.
Checkbox parts
{/* Styling the label and description parts */}
<Checkbox
label="Control Text Label"
size="large"
description="Please enter a guide description"
className="bg-neutral-secondary"
classNames={{
checkboxPrimitiveControl: "bg-critical hover:bg-critical-hover",
checkboxPrimitiveIcon: "bg-accent",
label: "text-body-14 text-tertiary",
descriptionTrack: "gap-1 ",
description: "text-positive",
spacer: "h-8",
}}
/>
{/* Styling the error parts */}
<Checkbox
label="Control Text Label"
size="large"
errorMessage="Error message goes here"
classNames={{
errorTrack: "text-caution",
errorIcon: "text-caution",
errorMessage: "text-caution",
}}
/>
Stylable Parts | Description |
---|---|
root | The root container of the checkbox, wrapping all inner components. |
checkboxPrimitiveRoot | The base container for the primitive checkbox structure. |
checkboxPrimitiveInput | The input element for the checkbox, where the value is stored. |
checkboxPrimitiveControl | The container for the control element, which visually represents the checked/unchecked state. |
checkboxPrimitiveIcon | The icon displayed within the checkbox when it is checked. |
label | The text label associated with the checkbox. |
descriptionTrack | Wrapper for the description text when it appears alongside the checkbox. |
description | Description text providing additional information about the checkbox. |
spacer | A spacer element used to create a gap between the description text and the start of the description track to maintain alignment for description text and label. |
errorTrack | The container for error messages when the checkbox is invalid. |
errorIcon | Icon displayed to indicate an error state, typically styled to match the error message. |
errorMessage | Text of the error message, providing feedback when validation fails. |
Usage guidelines
Do
- List, form, or table selections: Utilize
checkboxes
in lists, forms, or tables to present users with multiple, related options where selecting all, none, or some choices is necessary. - Accompanying
field
andInlineField
components: Include checkboxes in forms alongsidefield
andInlineField
components or in constrained spaces where atoggle
might be impractical due to size limitations. - Non-immediate selections: Opt for checkboxes when the user's selection does not take immediate effect and requires submission of a form for changes to occur.
Don’t
- Exclusive choices: Avoid checkboxes in situations where users can only choose one option out of multiple, related choices. Instead, use a
RadioGroup
to enforce exclusivity. - Immediate selections, especially on mobile: Refrain from using
checkboxes
when a selection needs to take immediate effect, particularly in mobile contexts. Instead, employ atoggle
for swift and direct interactions. - Ambiguous visual feedback: Steer clear of
checkboxes
when the visual distinction between turning a feature on or off is unclear. In such cases, aToggle
is recommended for its clarity in indicating the on/off state.
Best practices
Do
Employ checkboxes to enable the multi-selection of interconnected list items.
Don’t
Opt for checkboxes when allowing for a single selection is required. Alternatively, use a RadioGroup for this purpose.
Do
In forms where the selection becomes effective only after submitting, utilize a singular checkbox.
Don’t
Utilize a Checkbox for instant toggling of a state. Alternatively, use a Toggle for this purpose.
Do
Maintain concise and clear labels, legends and descriptions to prevent an overload of text that may impede scanning and slow down the user.
Don’t
Avoid using extensive text that gets truncated or fails to provide clear instructions on the expected selection.