A Checkbox should be used for On/Off or Yes/No questions. Each checkbox should indicate a separate decision and can be organized into groups of similar options.

<Form>
    <Form.Group grouped>
        <label>Attributes</label>
        <Form.Checkbox label="Force User" />
        <Form.Checkbox label="Pilot" />
        <Form.Checkbox label="Bounty Hunter" />
    </Form.Group>

    <Form.Group grouped>
        <label>Subscribe</label>
        <Form.Checkbox label="Subscribe to updates" />
    </Form.Group>

</Form>
const DontDoThisExample = () => {
    const [attributes, setAttributes] = React.useState(0)
    const [subscribe, setsubscribe] = React.useState(0)
    return (
        <Form>
            <Form.Group grouped>
                <label>Attributes</label>
                <Form.Radio
                    label="Force User"
                    checked={attributes === 1}
                    onChange={() => setAttributes(1)}
                />
                <Form.Radio
                    label="Pilot"
                    checked={attributes === 2}
                    onChange={() => setAttributes(2)}
                />
                <Form.Radio
                    label="Bounty Hunter"
                    checked={attributes === 3}
                    onChange={() => setAttributes(3)}
                />
            </Form.Group>
            <Form.Group grouped>
                <label>Subscribe to updates</label>
                <Form.Radio
                    label="No"
                    checked={subscribe === 1}
                    onChange={() => setsubscribe(1)}
                />
                <Form.Radio
                    label="Yes"
                    checked={subscribe === 2}
                    onChange={() => setsubscribe(2)}
                />
            </Form.Group>
        </Form>
    )
}
render (DontDoThisExample)

Sizing

Checkboxes can be sized to be small, medium, and large. Small checkboxes are useful in small areas, and large checkboxes when a lot of whitespace is present.

const SizingExample = () => {
    const [value, setValue] = React.useState(["ForceUser", "Pilot"])

    const onChange = (value, checked) => {
        if(checked){
            setValue(prevState => [...prevState, value])
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
        }
    }

    return (
        <Form>
            <Form.Group grouped>
                <label>Small Checkbox</label>
                <Form.Checkbox
                    label="Force User" size="small"
                    value="ForceUser"
                    checked={value.includes("ForceUser")}
                    onChange={onChange}
                />
                <Form.Checkbox
                    label="Pilot"
                    value="Pilot"
                    size="small"
                    checked={value.includes("Pilot")}
                    onChange={onChange}
                />
                <Form.Checkbox
                    label="Bounty Hunter"
                    value="BountyHunter"
                    size="small"
                    checked={value.includes("BountyHunter")}
                    onChange={onChange}
                />
            </Form.Group>
        </Form>
    )
}
render (SizingExample)
<Form>
    <Form.Group grouped>
        <label>Medium Checkbox</label>
        <Form.Checkbox label="Force User" />
        <Form.Checkbox label="Pilot" />
        <Form.Checkbox label="Bounty Hunter" />
    </Form.Group>
</Form>
<Form>
    <Form.Group grouped>
        <label>Large Checkbox</label>
        <Form.Checkbox label="Force User" size="large" />
        <Form.Checkbox label="Pilot" size="large" />
        <Form.Checkbox label="Bounty Hunter" size="large" />
    </Form.Group>
</Form>

States

Checkboxes can be in an error state and a disabled state.

<Form>
  <Form.Group grouped>
    <label>Default States</label>
    <Form.Checkbox checked label="Force User" />
    <Form.Checkbox label="Pilot" />
  </Form.Group>
</Form>
<Form>
  <Form.Group grouped>
    <label>Error States</label>
    <Form.Checkbox error checked label="Force User" />
    <Form.Checkbox error label="Pilot" />
  </Form.Group>
</Form>
<Form>
    <Form.Group grouped>
        <label>Disabled States</label>
        <Form.Checkbox disabled checked label="Force User" />
        <Form.Checkbox disabled label="Pilot" />
    </Form.Group>
</Form>

Labels and Helper Text

No Label Checkboxes

A checkbox can be isolated, without margins or label text. This is useful when checkboxes are placed in tables.

<Checkbox />

Label Help

Labels can have a help icon with a tooltip to provide additional context to a label.

<Form>
    <Form.Checkbox
        label="Checkbox Label"
        labelProps={{
            help: "This is help text",
            direction: 'r'
        }}
    />
</Form>

Helper Text

<Form>
    <Form.Checkbox
        description={<span>Our terms of service can be found <Link primary>here</Link></span>}
        label="I Agree to Terms of Service"
    />
    <Form.Checkbox
        error="You must agree to create your account."
        label="I Agree to Terms of Service"
    />
    <Form.Checkbox
        description={<span>Our terms of service can be found <Link primary>here</Link></span>}
        error="You must agree to create your account."
        label="I Agree to Terms of Service"
    />
</Form>

Indeterminate Checkboxes

Checkboxes can also be in an indeterminate state. This state is commonly used on checkboxes that control groups of items such as the bulk selection checkbox in Gmail.

Clicking a parent checkbox typically either selects or deselects all child checkboxes. When clicking a parent checkbox in an indeterminate state, default to select all.

const IndeterminateExample = () => {
    const [value, setValue] = React.useState([])

    const options = [
        { key: 1, value: 1, text: "Mercury" },
        { key: 2, value: 2, text: "Venus" },
        { key: 3, value: 3, text: "Earth" },
        { key: 4, value: 4, text: "Mars" }
    ];

    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
        }
    };

    const selectAll = (value, checked) => {
        if (checked) {
            setValue(options.map(n => n.value))
        } else {
            setValue([])
        }
    };
    return (
        <Form>
            <Checkbox
                checked={value.length == options.length}
                indeterminate={value.length > 0 && value.length !== options.length}
                label="Planets"
                value="thePlanets"
                key="0"
                onChange={selectAll}
            />
            <Form.Group grouped>
                {options.map((checkbox) => (
                        <Form.Checkbox
                            checked={value.includes(checkbox.value)}
                            key={checkbox.key}
                            value={checkbox.value}
                            label={checkbox.text}
                            onChange={onChange}
                            className="m-l-4-i"
                        />
                ))}
            </Form.Group>
        </Form>
    )
}
render (IndeterminateExample)

Custom Label Position

Checkboxes by default have their label to the left. A custom text label can be applied using the standard label, for, and id combination found with HTML checkboxes.

Examples of a label on the left

<Form style={{width: '155px'}}>
    <Form.Group grouped>
        <Stack
            alignItems="center"
            justifyContent="space-between"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id1"
                className="ta-right m-r-1"
            >
                Short Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id1"
                name="Checkbox-sample"
            />
        </Stack>
        <Stack
            alignItems="center"
            justifyContent="space-between"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id2"
                className="ta-right m-r-1"
            >
                Custom Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id2"
                name="Checkbox-sample"
            />
        </Stack>
        <Stack
            alignItems="center"
            justifyContent="space-between"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id3"
                className="ta-right m-r-1"
            >
                A Longer Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id3"
                name="Checkbox-sample"
            />
        </Stack>
    </Form.Group>
</Form>
<Form>
    <Form.Group grouped>
        <Stack
            alignItems="center"
            justifyContent="flex-end"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id4"
                className="ta-right m-r-1 m-t-1"
            >
                Short Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id4"
                name="Checkbox-sample"
                className="m-t-0-i"
            />
        </Stack>
        <Stack
            alignItems="center"
            justifyContent="flex-end"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id5"
                className="ta-right m-r-1 m-t-1"
            >
                Custom Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id5"
                name="Checkbox-sample"
                className="m-t-0-i"
            />
        </Stack>
        <Stack
            alignItems="center"
            justifyContent="flex-end"
        >
            <BodyText
                el="label"
                htmlFor="checkbox-id6"
                className="ta-right m-r-1 m-t-1"
            >
                A Longer Label
            </BodyText>
            <Form.Checkbox
                id="checkbox-id6"
                name="Checkbox-sample"
                className="m-t-0-i"
            />
        </Stack>
    </Form.Group>
</Form>

Best practices

Checkboxes should:

  • Work independently from each other: selecting one checkbox shouldn’t change the selection status of another checkbox in the list. The exception is when a checkbox is used to make a bulk selection of multiple items.
  • Be framed positively: for example, Turn on notifications instead of Turn off notifications
  • Always have a label when used to toggle a setting on or off
  • Be listed according to a logical order, whether it’s alphabetical, numerical, time-based, or some other clear system.
  • Link to more information or include a subtitle as required to provide more explanation. Don’t rely on tooltips to explain a checkbox.

Related Components

  • To build a full form, use the Form component.
  • For more than 5 options, like choosing tags, a Select with multiselect support could be a better option.
  • To present a list of options where users can only make a single choice, use the Radio component.
  • To build more prominent checkboxes, or with complex labels, use the Togglebox component.
  • For actions that have immediate results, use the Toggle Switch

Importing

We recommend using the Form shorthand component <Form.Checkbox />. It automatically provide the correct Form grouping structure and spacing. You can import the standalone component for custom Form layouts.

import { Checkbox } from '@servicetitan/design-system';