sdxc

Type to search, or start from one of these:

CheckboxGroup

A landmark grouping independently toggled checkbox controls into one related set.

Severity 1 pages go to every channel you keep on.

View code
let chosen = new Set(["email"]);

<div mix={[vstack({ gap: 2, align: "stretch" }), maxIs("26rem")]}>
	<CheckboxGroup
		orientation="vertical"
		aria-labelledby="preview-channels-label"
		aria-describedby="preview-channels-hint preview-channels-error"
		aria-invalid={chosen.size === 0 ? "true" : undefined}
		mix={[vstack({ gap: 3, align: "stretch" })]}
	>
		<Label id="preview-channels-label">Page me about incidents on</Label>

		{CHANNELS.map((channel) => (
			<Checkbox
				key={channel.value}
				name="channels"
				value={channel.value}
				checked={chosen.has(channel.value)}
				disabled={channel.disabled}
				mix={[
					ariaChecked(),
					on<HTMLInputElement, "change">("change", (event) => {
						if (event.currentTarget.checked) chosen.add(channel.value);
						else chosen.delete(channel.value);
						void handle.update();
					}),
				]}
			>
				<span mix={[vstack({ gap: 0, align: "start" })]}>
					<span mix={[text("sm")]}>{channel.label}</span>
					<span mix={[text("xs"), fg("neutral")]}>{channel.hint}</span>
				</span>
			</Checkbox>
		))}
	</CheckboxGroup>

	<Description id="preview-channels-hint">
		Severity 1 pages go to every channel you keep on.
	</Description>
	<FieldError id="preview-channels-error" hidden={chosen.size > 0}>
		Pick at least one channel.
	</FieldError>
</div>

Installation

An ordinary dependency: install it, import the theme once, and import the component where it is used.

npm add @sdxc/ui
import "@sdxc/ui/theme.css";

Usage

import { CheckboxGroup } from "@sdxc/ui";

Lays checkbox children out in a column, or a row when orientation is "horizontal"; each nested checkbox keeps its own checked state, name, and value. aria-invalid="true" recolors plain text composed alongside.

Examples

<CheckboxGroup aria-label={t("notifications.label")} orientation="horizontal">
	<Checkbox name="notify" value="email">{t("notifications.email")}</Checkbox>
	<Checkbox name="notify" value="sms">{t("notifications.sms")}</Checkbox>
	<Checkbox name="notify" value="push">{t("notifications.push")}</Checkbox>
</CheckboxGroup>
<CheckboxGroup aria-labelledby="terms-label" aria-invalid="true" aria-describedby="terms-error">
	<Label id="terms-label">{t("terms.label")}</Label>
	<Checkbox name="terms" value="accepted" required>{t("terms.accept")}</Checkbox>
	<FieldError id="terms-error">{t("terms.required")}</FieldError>
</CheckboxGroup>

Props

Read from the component's own types, so every prop, every default and every allowed value is listed.

PropTypeDescription
orientation?"horizontal" | "vertical"Layout axis. Defaults to DEFAULT_ORIENTATION.

Also accepts everything in TagProps<"div">.

Types

NameValuesWhat it decides
Orientation"horizontal" | "vertical"Axis a group's checkboxes lay out along: a single column, or a single row.