Skip to content

Checkbox

Terminal-styled checkbox with [x] and bullet variants. Standalone or CheckboxGroup with built-in arrow navigation.

Preview

Installation

$pnpm exec dgadd add ui/checkbox
[Installs to]src/components/ui/checkbox[Item]ui/checkbox

dgadd is not public on npm yet. Until the first release, pack @diffgazer/add from the repository and install that tarball into this app, which is what puts dgadd on pnpm exec.

UI components require Tailwind CSS v4. Local copy mode imports src/styles/styles.css; package mode uses @diffgazer/ui CSS once packages are available.

Usage

tsx
"use client";import { useState } from "react";import { Checkbox } from "@/components/ui/checkbox";export default function CheckboxDefault() {  const [checked, setChecked] = useState(false);  return <Checkbox checked={checked} onChange={setChecked} label="Accept terms and conditions" />;}

Examples

Variants

Preview

Highlight, Invalid, and Disabled

Preview

Group

Preview

Checklist

Preview

API Reference

Checkbox

NameTypeDefaultDescription
checkedboolean | "indeterminate"Controlled checked state. Use "indeterminate" for the mixed visual state.
defaultCheckedbooleanfalseInitial checked state for uncontrolled usage.
onChange(checked: boolean) => voidCalled when the boolean checked state changes.
valuestring"on"Hidden native input value used for form submission.
namestringHidden native input name used for form submission.
requiredbooleanfalseMarks the hidden native checkbox as required.
labelReactNodeVisible label associated with the custom checkbox.
descriptionReactNodeVisible description wired with aria-describedby.
disabledbooleanfalseDisables the custom control and hidden input.
size"sm" | "md" | "lg""md"Selectable control size token.
variant"x" | "bullet""x"Indicator style.
strikethroughbooleanfalseApplies muted line-through styling to the label when checked.

CheckboxGroup

NameTypeDefaultDescription
valuestring[]Controlled selected item values.
defaultValuestring[][]Initial selected values for uncontrolled usage.
onChange(value: string[]) => voidCalled when the selected values change.
highlightedstring | nullControlled highlighted item value for keyboard navigation.
onHighlightChange(value: string | null) => voidCalled when keyboard navigation highlights a new item or clears highlight.
wrapbooleantrueWhether arrow-key navigation wraps at the first and last item.
keyboardNavigationbooleantrueEnable built-in arrow-key navigation.
onNavigationBoundaryReached(direction: "previous" | "next", event: KeyboardEvent, key: string) => voidCalled when non-wrapping navigation reaches the first or last item. Use event/key to decide whether to hand focus to adjacent controls.
autoFocusbooleanfalseFocuses the highlighted, selected, or first enabled item when the group becomes active.
disabledbooleanfalseDisables the group and all items.
namestringShared hidden native input name for grouped form submission.
requiredbooleanfalseRequires at least one enabled item to be selected.
labelstringVisible group label rendered before the items. Also names the group unless aria-label overrides it.
aria-labelstringExplicit accessible name for the group. Overrides the visible label when supplied.
aria-labelledbystringID reference for an external label. Use when another element already names the group. Composed with the visible label unless aria-label is supplied.

CheckboxItem

NameTypeDefaultDescription
valuerequiredstringItem value. Must be unique within the group.
labelrequiredReactNodeVisible item label.
descriptionReactNodeVisible item description wired with aria-describedby.
disabledbooleanfalseDisables the item.

Data attributes

AttributeApplies toValuesDescription
data-stateCheckbox / CheckboxItem"checked" | "unchecked" | "indeterminate"Boolean visual state for styling the custom control.
data-disabledCheckbox / CheckboxItempresent when disabledMarks disabled controls and group items.
data-highlightedCheckbox / CheckboxItempresent when highlightedMarks the current keyboard-highlighted group item.
data-valueCheckbox / CheckboxItemitem valueStable item value used by group navigation and form submission wiring.
data-diffgazer-selectable-ownerCheckboxGroup"checkbox"Scopes nested selectable-item discovery for keyboard navigation.

Accessibility

Keyboard Navigation

CheckboxGroup includes arrow-key navigation — with the vim aliases j/k — with wrapping and real focus movement. Control highlighted/onHighlightChange when external state coordination is needed, use autoFocus when activating a composite region, use keyboardNavigation to suspend only arrow handling, and use onNavigationBoundaryReached for composite focus handoff. Standalone Checkbox responds to Space when focused.

KeyAction
SpaceToggles a focused standalone Checkbox or CheckboxItem.
ArrowUp / kMoves focus to the previous enabled CheckboxItem inside CheckboxGroup.
ArrowDown / jMoves focus to the next enabled CheckboxItem inside CheckboxGroup.
Home / EndMoves focus to the first or last enabled item.
EnterToggles the focused/highlighted enabled group item.

Group with built-in keyboard navigation

Preview

Notes

Requires @diffgazer/keys (package mode)

CheckboxGroup's arrow-key navigation imports from the required @diffgazer/keys peer. Package consumers must install @diffgazer/keys with @diffgazer/ui; packages are not yet published to npm, so until the first release install both from locally packed tarballs. Importing @diffgazer/ui/components/checkbox without keys fails at module load with an error naming the missing @diffgazer/keys package. Standalone Checkbox still needs it because the subpath bundles the group. Copy/dgadd consumers do not need the package — copy mode rewrites the keyboard hooks to local source.

Indeterminate State

Checkbox supports a third state: checked='indeterminate' renders [-] in both indicator variants. This is useful for parent checkboxes representing partially-selected groups.

Glyph Hierarchy

The brackets are chrome and render muted; the inner mark keeps the control's tone at bold weight. A checked row is therefore the only place full-contrast ink appears in the glyph column, so a long checklist can be scanned instead of read bracket by bracket. The visible text is unchanged — the indicator still reads [x], [ ], or [-] — and the whole cell stays aria-hidden.

Indicator Variants

variant='x' (default) marks the checked state with [x]; variant='bullet' marks it with [*]. Both keep the same three-character width so mixed lists stay aligned, and neither reuses Radio's [●] dot — a checkbox never reads as a radio.

Built-in Navigation

CheckboxGroup handles arrow-key navigation with real focus movement through useNavigation. Enter toggles the focused/highlighted enabled item; Space continues to work through native/item semantics. Use autoFocus to focus the highlighted, selected, or first enabled item when the group becomes active. Use highlighted, onHighlightChange, keyboardNavigation, and onNavigationBoundaryReached when coordinating highlight state across adjacent UI. Every item value must be unique within a group.

Strikethrough (Checklist Mode)

Pass strikethrough to Checkbox or CheckboxGroup to apply line-through styling and muted color to checked item labels.

Source

Install via CLI: pnpm exec dgadd add ui/checkbox. Keyboard hooks are included as standalone copies. For the full experience, use --integration keys.

Highlighted source loads after this disclosure opens. Browse the source repository.