Actions
ToggleGroup
A row of related toggles that share one value, such as text alignment or bold, italic and underline in a toolbar. One toggle is pressed at a time unless multiple is set, which makes the value a list. The arrow keys move between toggles, and each keeps its name with aria-pressed for its state.
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/toggle-group#v1.2.13Or, with the @ouro namespace set up:
npx shadcn@latest add @ouro/ouro-base @ouro/toggle-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/toggle-group#v1.2.13 ourostack/ouro-ui/toggle-group-tests#v1.2.13import { ToggleGroup } from "@/components/ouro/toggle/toggle-group";Paths use shadcn's default @/ alias; the CLI rewrites them to yours.
Example
<ToggleGroup
label="Text style"
hideLabel
multiple
items={[
{ value: "bold", label: "Bold", icon: BoldIcon, hideLabel: true },
{ value: "italic", label: "Italic", icon: ItalicIcon, hideLabel: true },
]}
value={styles}
onValueChange={setStyles}
/>Use instead when
- Use
SegmentedControlinstead when exactly one choice is always selected and switches a view. - Use
RadioGrouporCheckboxGroupinstead for a form value that is submitted, and oneTogglefor a single on/off button.
Props
The props the modes share. Type: ToggleGroupProps.
className- Type:
string - Layout only: margins, grid placement (
mt-4). Appearance classes warn in development. disabled- Type:
boolean - Disables every toggle.
hideLabel- Type:
boolean - Hides the group's label visually; it still names the group. Set it on a toolbar whose toggles say what it is.
items(required)- Type:
readonly ToggleGroupItem[] - The toggles, in order.
label(required)- Type:
string - Names the group ("Text style"). Shown above it unless
hideLabelis set; screen readers always hear it. ref- Type:
Ref<HTMLDivElement> - Reaches the group element (
role="group"). size- Type:
"sm" | "md" | "lg" - Default:
"md" - Every toggle's size, as Button's. shadcn's
defaultismd. variant- Type:
"outline" | "plain" - Default:
"plain" plaintoggles have no border until pressed;outlineones always have one. shadcn'sdefaultisplain.
Modes
ToggleGroupProps is a union: pass the props of exactly one mode. Mixing them is a type error.
Multiple: ToggleGroupMultipleProps
With multiple, any number of toggles pressed: the value is a list of item values.
defaultValue- Type:
readonly string[] - Default: []
- The toggles pressed first, when the group keeps its own state.
multiple(required)- Type:
true - Allows several toggles pressed at once, and makes the value a list.
onValueChange- Type:
((value: string[]) => void) - Called with the pressed toggles' values, in item order.
value- Type:
readonly string[] - The pressed toggles' values, when you control them. Pair it with
onValueChange.
Single: ToggleGroupSingleProps
One toggle pressed at a time, the default: the value is one item's value, or null for none.
defaultValue- Type:
string | null - Default: null
- The toggle pressed first, when the group keeps its own state.
multiple- Type:
false - Allows several toggles pressed at once, and makes the value a list.
onValueChange- Type:
((value: string | null) => void) - Called with the pressed toggle's value, or
nullwhen the pressed one is pressed again. value- Type:
string | null - The pressed toggle's value, or
nullfor none, when you control it. Pair it withonValueChange.
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.
children: Not a prop. The toggles come fromitems:<ToggleGroup items={[{ value: "bold", label: "Bold" }]}>.onChange: Not a prop. Ouro UI usesonValueChange, which gets the value:<ToggleGroup onValueChange={(value) => ...}>.options: Not a prop. Ouro UI usesitems:<ToggleGroup items={[{ value, label }]}>.type: Not a prop. One toggle at a time is the default;multipleallows several:<ToggleGroup multiple>.
className is for layout only
Pass margins, width and grid placement (mt-4, w-full, col-span-2). Your classes always win over Ouro UI's: ToggleGroup merges className last with cn (tailwind-merge), so a class that conflicts with its own replaces it.layout-classes
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
ToggleGroupItem
One toggle in a ToggleGroup.
interface ToggleGroupItem {
/** Identifies the toggle: `value`, `defaultValue` and `onValueChange` use it. Unique within the group. */
value: string;
/** The toggle's name, shown unless `hideLabel` is set. It stays the same while pressed. */
label: string;
/** Icon before the label, or alone with `hideLabel`. Pass the component: `icon: BoldIcon`. */
icon?: ToggleIcon | undefined;
/** Shows only the icon; the label stays the toggle's name for screen readers. */
hideLabel?: boolean | undefined;
/** Shows the toggle but keeps it from being pressed. */
disabled?: boolean | undefined;
}Claim sources
- layout-classes: test:registry/ouro/components/ouro/toggle/toggle-group.test.tsx::ToggleGroup > forwards its ref to the group and lets layout classes win on the root
verify:testExists(registry/ouro/components/ouro/toggle/toggle-group.test.tsx::ToggleGroup > forwards its ref to the group and lets layout classes win on the root)