sdxc

[ @sdxc/ui ]

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 remix
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

Horizontal

View code
<CheckboxGroup aria-label="Notify me by" orientation="horizontal">
	<Checkbox name="notify" value="email" defaultChecked>Email</Checkbox>
	<Checkbox name="notify" value="sms">SMS</Checkbox>
	<Checkbox name="notify" value="push">Push</Checkbox>
</CheckboxGroup>

Invalid

Accept the terms to create your account.
View code
<CheckboxGroup aria-labelledby="terms-label" aria-invalid="true" aria-describedby="terms-error">
	<Label id="terms-label">Terms of service</Label>
	<Checkbox name="terms" value="accepted" required>
		I accept the Acme terms of service
	</Checkbox>
	<FieldError id="terms-error">Accept the terms to create your account.</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.

Written by Sergio Xalambrí. Follow @sergiodxa for new packages, or sponsor the work.