Forms
CheckboxGroup
A group of checkboxes under one legend, on the Field contract, for picking any number of choices: pass legend, and options (or Checkbox children). value is the list of checked values; with name, each checked box submits name=value with its form. error and required apply to the whole group.
Install
Once per app, with Tailwind CSS v4 and an @/* path alias (Ouro HX is built on Base UI, so --base base; skip -t in an existing app):
npx shadcn@latest init --base base --preset nova --yes --no-monoreponpx shadcn@latest add ourostack/ouro-ui/ouro-base#v1.2.13Then the component. From v0.8.0 it installs only the helpers it imports and never touches your stylesheet (Installing):
npx shadcn@latest add ourostack/ouro-ui/checkbox-group#v1.2.13Or, with the @ouro namespace set up:
npx shadcn@latest add @ouro/ouro-base @ouro/checkbox-groupIts tests, stories and Playwright spec are optional. They need Vitest 4.1.11 or later, and from v0.8.0 never change a version your app has (Testing):
npx shadcn@latest add ourostack/ouro-ui/checkbox-group#v1.2.13 ourostack/ouro-ui/checkbox-group-tests#v1.2.13import { CheckboxGroup } from "@/components/ouro/checkbox/checkbox-group";Paths use shadcn's default @/ alias; the CLI rewrites them to yours.
Example
<CheckboxGroup
legend="Herbs"
name="herbs"
defaultValue={["basil"]}
options={[
{ value: "basil", label: "Basil", description: "Sweet and peppery." },
{ value: "mint", label: "Mint" },
]}
/>Use instead when
- Use
RadioGroupinstead when exactly one choice may be picked,Checkboxfor a single yes-or-no choice, andFieldsetto group different fields.
Props
The props the modes share. Type: CheckboxGroupProps.
className- Type:
string - Layout only: margins, width, grid placement (
mt-4,col-span-2). Appearance classes warn in development; style checkboxes in your theme. defaultValue- Type:
string[] - The values checked at first, for an uncontrolled group.
description- Type:
ReactNode - Supporting text under the legend, read after it through
aria-describedby. disabled- Type:
boolean - Disables every box and fades the group.
error- Type:
ReadonlyErrorMessages - What is wrong, from your server action or client check, shown under the choices; every box gets
aria-invalid. A message is text or a React node (one with a link); an empty string or array means valid. hideLegend- Type:
boolean - Hides the legend visually; screen readers still read it as the group's name.
legend(required)- Type:
string - What the group is, shown above the choices and read as the group's name. Required: a group of controls needs a name. To hide it visually, keep it and add
hideLegend. name- Type:
string - The form field name every checked box submits under, once per checked value.
onValueChange- Type:
((value: string[]) => void) - Called with every checked value, in the order they were checked, when one is checked or unchecked.
ref- Type:
Ref<HTMLDivElement> - The group element, a
<div role="group">. required- Type:
boolean - At least one box must be checked to submit the form: the legend gets a marker (and
requiredLabelfor screen readers), and the browser showsrequiredMessageuntil one is checked. HTML has no native "at least one" rule for checkboxes, so this check runs only once the page has hydrated: your server action must still check it. requiredLabel- Type:
string - Default:
"(required)" - What screen readers hear after the legend when
required, since no box can carryaria-required; the asterisk is what shows. Translate it here. requiredMessage- Type:
string - Default:
"Choose at least one." - What the browser says when
requiredand nothing is checked. Translate it here. value- Type:
string[] - The checked values, for a controlled group; pair it with
onValueChange.
Modes
CheckboxGroupProps is a union: pass the props of exactly one mode. Mixing them is a type error.
With children
children(required)- Type:
ReactNode - The choices as
Checkboxelements, each with avalue, for a layoutoptionscannot express.
Not in this mode (typed never):
options: Not with children: pass the choices one way.
With options
options(required)- Type:
CheckboxGroupOption[] - The choices, one box each, in order.
Not in this mode (typed never):
children: Not withoptions: pass the choices one way.
Don't use
These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.
errorMessage: Not a prop. Ouro UI useserror:<CheckboxGroup error="Required.">.helperText: Not a prop. Ouro UI usesdescription:<CheckboxGroup description="...">.invalid: Not a prop.errormarks the group invalid:<CheckboxGroup error="What is wrong">.isDisabled: Not a prop. Ouro UI usesdisabled:<CheckboxGroup disabled>.isInvalid: Not a prop.errormarks the group invalid:<CheckboxGroup error="What is wrong">.isRequired: Not a prop. Ouro UI usesrequired:<CheckboxGroup required>.items: Not a prop. Ouro UI usesoptions:options={[{ value: "basil", label: "Basil" }]}.label: Not a prop. A group is named by itslegend:<CheckboxGroup legend="Herbs">.onChange: Not a prop. Ouro UI usesonValueChange, which gets the checked values:onValueChange={setValues}.
className is for layout only
Pass margins, width and grid placement (mt-4, w-full, col-span-2).
Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (hover:, sm:) and any ! are removed, it starts with bg-, text-, border-, rounded-, shadow-, font-, ring-, from-, via-, to-, fill- or stroke-, or is border, rounded, shadow or ring, or has a dark: variant. Text wrapping, overflow and table layout classes (text-wrap, text-ellipsis, border-collapse) are layout and do not warn.
Alignment classes (text-center) warn too: set alignment on a parent element.
Types
CheckboxGroupOption
One choice in a CheckboxGroup's options.
interface CheckboxGroupOption {
/** What the box submits, and its entry in the group's `value`. */
value: string;
/** The choice's name, shown to the right of its box. */
label: string;
/** Supporting text under the label, read after it. */
description?: ReactNode | undefined;
/** Disables this one box. */
disabled?: boolean | undefined;
}ErrorMessage
One error message: text, or a React element for a message that carries a link or other markup.
type ErrorMessage = string | ReactElement;ReadonlyErrorMessages
A read-only message view accepted by fields and Form; mutable input arrays remain valid.
type ReadonlyErrorMessages = ErrorMessage | readonly ErrorMessage[];