const Example01 = () => {
    const [value, setValue] = React.useState(["Test2"])
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
        }
    };
    return (
        <div>
            <ToggleSwitch
                checked={value.includes("Test1")}
                label="Active"
                name="Toggle-1"
                onChange={onChange}
                value="Test1"
            />
            <br />
            <br />
            <ToggleSwitch
                checked={value.includes("Test2")}
                label="Active"
                name="Toggle-1"
                onChange={onChange}
                value="Test2"
            />
        </div>
    )
}
render (Example01)

Toggle Switch Labels

Toggle Switch labels are on the right side of the toggle element. They generally have two pieces: the action being taken, and the subject matter.

<div>
    <ToggleSwitch
        label="Show Audit Trail"
        name="Toggle-1"
        value="Test1"
    />
</div>

Label Help

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

<Form>
    <Form.ToggleSwitch
        label="Toggle Switch Label"
        labelProps={{
            help: "This is help text"
        }}
    />
</Form>

Action Only

Sometimes it make sense for the toggle's subject to be separated from the toggle itself. This is useful in a list-context or if the subject is tied to a more complex UI component such as a Card, Table, or Page title.

Action Only With Cards

const ActionOnlyWithCardsExample = () => {
    const [value, setValue] = React.useState(["Test2"])
    const [active, setActive] = React.useState(false)
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value]),
            setActive(!active)
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
            setActive(!active)
        }
    };
    return (

        <div>
            <Card sharp active={value.includes("Test1")} raised={value.includes("Test1")}>
                <Stack alignItems='center'>
                    <Stack.Item fill>
                        <BodyText size="large" bold>Report Form Widget</BodyText>
                        <BodyText subdued>Lorem ipsum dolar emit</BodyText>
                    </Stack.Item>
                    <Stack.Item>
                        <ToggleSwitch
                            checked={value.includes("Test1")}
                            label="Active"
                            name="Toggle-1"
                            onChange={onChange}
                            value="Test1"
                        />
                    </Stack.Item>
                </Stack>
            </Card>
            <Card sharp className="m-t-2" active={value.includes("Test2")} raised={value.includes("Test1")}>
                <Stack alignItems='center'>
                    <Stack.Item fill>
                        <BodyText size="large" bold>Audit Inventory Widget</BodyText>
                        <BodyText subdued>Lorem ipsum dolar emit</BodyText>
                    </Stack.Item>
                    <Stack.Item>
                        <ToggleSwitch
                            checked={value.includes("Test2")}
                            label="Active"
                            name="Toggle-2"
                            onChange={onChange}
                            value="Test2"
                        />
                    </Stack.Item>
                </Stack>
            </Card>
        </div>
    )
}
render (ActionOnlyWithCardsExample)

Action Only In a List

When scanning a set of options, it may make sense to separate the toggle's subject to the left. This can be done with caution: the user should be able to understand they are toggling the text to the left on or off.

---
<Form>
    <ToggleSwitch
        className="m-b-2 d-b"
        label="Show Technician Availability"
        name="Toggle-1"
        value="Test1"
    />
    <ToggleSwitch
        className="m-b-2 d-b"
        label="Show Job Audit"
        name="Toggle-1"
        value="Test1"
    />
    <ToggleSwitch
        className="m-b-2 d-b"
        label="Show Smart Estimates"
        name="Toggle-1"
        value="Test1"
    />
</Form>
<Stack alignItems="stretch">
    <Stack direction="column" justifyContent="space-between" className="flex-grow-1 m-r-4">
        <BodyText
            el="label"
            htmlFor="switch-id1"
        >
            Technician Availability
        </BodyText>
        <BodyText
            el="label"
            htmlFor="switch-id2"
        >
            Job Audit
        </BodyText>
        <BodyText
            el="label"
            htmlFor="switch-id3"
        >
            Smart Estimates
        </BodyText>
    </Stack>
    <Stack direction="column" justifyContent="space-between">
        <ToggleSwitch
            className="m-b-2"
            label="Enabled"
            name="Toggle-1"
            value="Test1"
            id="switch-id1"
        />
        <ToggleSwitch
            className="m-b-2"
            label="Enabled"
            name="Toggle-2"
            value="Test2"
            id="switch-id2"
        />
        <ToggleSwitch
            label="Enabled"
            name="Toggle-3"
            value="Test3"
            id="switch-id3"
        />
    </Stack>
</Stack>

No Label

A toggle switch can also have no label when the context of what it turns on or off can be clearly understood. A tooltip can also be applied to describe the toggle's current state.

const NoLabelExample = () => {
    const [value, setValue] = React.useState(["Test1",1])
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
        }
    };
    const getValue = (value) => {
        if (value) { return "enabled" }
        else { return "disabled" }
    };
    return (
        <Form className="example">
            <style>{`
                .example .field { margin-bottom: 24px !important; }
                .example .field > label { display: none !important; }
            `}</style>
            <Stack alignItems="center" justifyContent="space-between">
                <Form.Input
                    defaultValue="Leia Doe"
                    disabled={!value.includes("Test1")}
                    label=""
                />
                <Form.Input
                    defaultValue="leia12345@email.com"
                    disabled={!value.includes("Test1")}
                    label=""
                />
                <Form.Input
                    defaultValue="(123) 456–7890"
                    disabled={!value.includes("Test1")}
                    label=""
                />
                <Tooltip text={"Leia Doe account is " + getValue(value.includes("Test1"))} direction="tl">
                    <ToggleSwitch
                        checked={value.includes("Test1")}
                        className="m-b-3"
                        name="Toggle-1"
                        onChange={onChange}
                        value="Test1"
                    />
                </Tooltip>
            </Stack>
            <Stack alignItems="center" justifyContent="space-between">
                <Form.Input
                    defaultValue="Jane Spencer"
                    disabled={!value.includes("Test2")}
                    label=""
                />
                <Form.Input
                    defaultValue="janespencer@email.com"
                    disabled={!value.includes("Test2")}
                    label=""
                />
                <Form.Input
                    defaultValue="(555) 456–7890"
                    disabled={!value.includes("Test2")}
                    label=""
                />
                <Tooltip text={"Jane Spencer account is " + getValue(value.includes("Test2"))} direction="tl">
                    <ToggleSwitch
                        checked={value.includes("Test2")}
                        className="m-b-3"
                        name="Toggle-1"
                        onChange={onChange}
                        value="Test2"
                    />
                </Tooltip>
            </Stack>
            <Stack alignItems="center" justifyContent="space-between">
                <Form.Input
                    defaultValue="Bob Smith"
                    disabled={!value.includes("Test3")}
                    label=""
                />
                <Form.Input
                    defaultValue="bob@email.com"
                    disabled={!value.includes("Test3")}
                    label=""
                />
                <Form.Input
                    defaultValue="(492) 451–1290"
                    disabled={!value.includes("Test3")}
                    label=""
                />
                <Tooltip text={"Bob Smith account is " + getValue(value.includes("Test3"))} direction="tl">
                    <ToggleSwitch
                        checked={value.includes("Test3")}
                        className="m-b-3"
                        name="Toggle-1"
                        onChange={onChange}
                        value="Test3"
                    />
                </Tooltip>
            </Stack>
        </Form>
    )
}
render (NoLabelExample)

Constant Labeling

The Toggle Switch label is always the same text. It describes what the "ON" state of the toggle is. The label should not switch based off the toggle's state.

<Form>
    <ToggleSwitch
        label="Active"
        name="Toggle-1"
        value="Test1"
    />
</Form>
const ConstantLabelingExample = () => {
    const [value, setValue] = React.useState([])
    const [text, setText] = React.useState("Inactive")
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
            setText("Active")
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
            setText("Inactive")
        }
    };
    return (
        <Form>
            <ToggleSwitch
                label={text}
                name="Toggle-1"
                onChange={onChange}
                value="Test1"
            />
        </Form>
    )
}
render (ConstantLabelingExample)

Positive Wording

Labels in general should be positive. Since the label and toggle are generally thought of as turning something on, labels should reenforce this. Examples include “Show”, “Hide”, “Activate”, “Group [by]”, “Track”, and “Activate”. Negative labeling can be used with caution, if it makes sense to a user to perform a negative action.

<Form>
    <ToggleSwitch
        label="Show Tech Map"
        name="Toggle-1"
        value="Test1"
    />
</Form>
<Form>
    <ToggleSwitch
        label="Hide Tech Map"
        name="Toggle-1"
        value="Test1"
    />
</Form>

Immediate Results

In general, toggle switches should provide immediate feedback that something has occurred.

const ImmediateResultsExample = () => {
    const [value, setValue] = React.useState([])
    const [disabled, setDisabled] = React.useState(true)
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
            setDisabled(!disabled)
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
            setDisabled(!disabled)
        }
    };
    return (
        <Form>
            <ToggleSwitch
                checked={value.includes("Test1")}
                label="Show Different Name"
                name="Toggle-1"
                onChange={onChange}
                value="Test1"
            />
            <Form.Group widths="equal" className="p-t-3">
                <Form.Input label="First Name" defaultValue="Jane" placeholder="Leia" disabled={disabled} />
                <Form.Input label="Last Name" defaultValue="Doe" placeholder="Organa" disabled={disabled} />
            </Form.Group>
        </Form>
    )
}
render (ImmediateResultsExample)

Consider using a Checkbox when a button needs to be pressed in for the setting to take place.

<Form>
    <Form.Checkbox
        label="Show Option 1"
        name="Check-1"
        value="Test1"
    />
    <Form.Checkbox
        label="Show Option 2"
        name="Check-2"
        value="Test2"
    />
    <Form.Checkbox
        label="Show Option 3"
        name="Check-3"
        value="Test3"
    />
    <Form.Button full primary>Apply</Form.Button>
</Form>
const Example02 = () => {
    const [value, setValue] = React.useState([])
    const [disabled, setDisabled] = React.useState(true)
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
            setDisabled(!disabled)
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
            setDisabled(!disabled)
        }
    };
    return (
        <Form>
            <Form.ToggleSwitch
                checked={value.includes("Test1")}
                label="Show Option 1"
                name="Toggle-1"
                onChange={onChange}
                value="Test1"
            />
            <Form.ToggleSwitch
                checked={value.includes("Test2")}
                label="Show Option 2"
                name="Toggle-2"
                onChange={onChange}
                value="Test2"
            />
            <Form.ToggleSwitch
                checked={value.includes("Test3")}
                label="Show Option 3"
                name="Toggle-3"
                onChange={onChange}
                value="Test3"
            />
            <Form.Button full primary>Apply</Form.Button>
        </Form>
    )
}
render (Example02)

In a form

A Toggle Switch can also be added into a Form component.

const InAFormExample = () => {
    const [planet, setPlanet] = React.useState()
    const [duration, setDuration] = React.useState()
    const [disabled, setDisabled] = React.useState(true)

    return (
    <Form>
        <Headline el="div" className="m-b-4">Add Contact</Headline>
        <Form.Group widths="equal">
            <Form.Input label="First Name" placeholder="Leia" />
            <Form.Input label="Last Name" placeholder="Organa" />
        </Form.Group>
        <Form.Select
            label="Home Planet"
            placeholder="Choose Planet"
            options={[
                {key:1, value: 1, text: 'Alderaan'},
                {key:2, value: 2, text: 'Bespin'},
                {key:3, value: 3, text: 'Coruscant'},
                {key:4, value: 4, text: 'Dagobah'},
                {key:5, value: 5, text: 'Hoth'},
                {key:6, value: 6, text: 'Kashyyyk'},
                {key:7, value: 7, text: 'Naboo',},
                {key:8, value: 8, text: 'Tatooine'},
                {key:9, value: 9, text: 'Yavin'},
            ]}
            onChange={(event, value) => setPlanet(value.value)}
            value={planet}
        />
        <Form.ToggleSwitch
            checked={!disabled}
            label="Track Tax Values"
            name="Toggle-1"
            onChange={() => setDisabled(!disabled)}
            value="Test1"
        />
        <Form.Group>
            <Form.Input disabled={disabled} label="Tax Rate" placeholder="8.45%" />
            <Form.Input disabled={disabled} label="Duration" placeholder="3" />
            <Form.Select
                disabled={disabled}
                label=""
                placeholder="Choose Time Length"
                options={[
                    {key:1, value: 1, text: 'Days'},
                    {key:2, value: 2, text: 'Weeks'},
                    {key:3, value: 3, text: 'Months'}
                ]}
                onChange={(event, value) => setDuration(value.value)}
                value={duration}
            />
        </Form.Group>
    </Form>
    )
}
render (InAFormExample)

Disabled State

<div>
    <ToggleSwitch
        checked
        className="d-b m-b-2"
        label="Default On"
        name="Toggle-1"
        value="Test1"
    />
    <ToggleSwitch
        className="d-b m-b-4"
        label="Default Off"
        name="Toggle-1"
        value="Test1"
    />
    <ToggleSwitch
        checked
        className="d-b m-b-2"
        disabled
        label="Disabled On"
        name="Toggle-1"
        value="Test1"
    />
    <ToggleSwitch
        disabled
        label="Disabled Off"
        name="Toggle-1"
        value="Test1"
    />
</div>
const Example03 = () => {
    const [value, setValue] = React.useState(["Test1", "Test2", "Test3"])
    const onChange = (value, checked) => {
        if (checked) {
            setValue(prevState => [...prevState, value])
        } else {
            setValue(prevState => [...prevState].filter(item => item !== value))
        }
    };
    return (
        <div>
            <BodyText className="m-b-2">Guests can</BodyText>
            <ToggleSwitch
                checked={value.includes("Test1")}
                className="d-b m-b-2"
                label="Modify event"
                name="Toggle-1"
                onChange={onChange}
                value="Test1"
            />
            <ToggleSwitch
                checked={value.includes("Test2") || value.includes("Test1")}
                className="d-b m-b-2"
                disabled={value.includes("Test1")}
                label="Invite others"
                name="Toggle-1"
                onChange={onChange}
                value="Test2"
            />
            <ToggleSwitch
                checked={value.includes("Test3") || value.includes("Test1")}
                className="d-b m-b-2"
                disabled={value.includes("Test1")}
                label="See guest list"
                name="Toggle-1"
                onChange={onChange}
                value="Test3"
            />
        </div>
    )
}
render (Example03)

Best Practices

  • Toggle Switches in general should provide immediate results.
  • Toggle Switch options should be reducible to an On/Off choice.
  • Labels should be framed positively.
  • If using a Tooltip, display the current Toggle Switch state.
  • When in doubt, use the label to describe both the action and the subject of the Toggle Switch.
  • Use visual indicators such as disabled and active states on other elements to reenforce the state of the Toggle Switch.

Related Components

  • When needing a Yes/No choice, or needing to submit a form, use a Checkbox.

  • For more complex, mutually exclusive choices, use a Button Toggle or Radio.


Importing

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