A set of toggles sharing one value: single (a clearable radio set) or multiple.
ToggleGroup sits its items on one recessed track and lifts the pressed ones out as solid keys. type="single" allows at most one pressed item, and pressing it again clears the value; type="multiple" allows any number.
It has one tab stop: arrow keys move between items and Space or Enter presses. For a view switch where one option is always chosen, SegmentedControl reads better.
Usage
import { ToggleGroup } from "@/components/ui";
<ToggleGroup
type="single"
aria-label="Text alignment"
value={align}
onValueChange={setAlign}
items={[
{ value: "left", icon: <AlignLeft size={16} />, "aria-label": "Align left" },
{ value: "center", icon: <AlignCenter size={16} />, "aria-label": "Align centre" },
]}
/>Examples
Single and multiple
Text items
API
Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.
ToggleGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsRequired | ReadonlyArray<ToggleGroupItem> | ||
| aria-labelRequired | string | Names the group: "Text formatting", "Days". | |
| variant | "ghost" | "outline" | "ghost" | "outline" | "outline" | |
| size | "sm" | "md" | "sm" | "md" | "md" | |
| orientation | "horizontal" | "vertical" | "horizontal" | "vertical" | "horizontal" | |
| disabled | boolean | ||
| className | string | ||
| typeRequired | "single" | "multiple" | single: at most one item pressed, like a radio group that can be cleared. | |
| valueRequired | string | null | ReadonlyArray<string> | ||
| onValueChangeRequired | (value: string | null) => void | (value: string[]) => void |
Theme tokens
Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.
| Token | Default | Live value |
|---|---|---|
| --toggle-height-md | var(--control-h-md) | … |
| --toggle-height-sm | var(--control-h-sm) | … |
| --toggle-ink | var(--ink-muted) | … |
| --toggle-on-bg | var(--wash-active) / var(--surface-solid) | … |
| --toggle-on-ink | var(--ink-brand) | … |
| --toggle-on-line | var(--line-brand-strong) | … |
| --toggle-radius | var(--r-md) / var(--r-sm) | … |
System tokens it reads
| Token | Default | Live value |
|---|---|---|
| --border-w | tokens.css | … |
| --control-h-md | tokens.css | … |
| --control-h-sm | tokens.css | … |
| --density | tokens.css | … |
| --dur | tokens.css | … |
| --ease | tokens.css | … |
| --focus-ring | tokens.css | … |
| --font-body | tokens.css | … |
| --ink-brand | tokens.css | … |
| --ink-disabled | tokens.css | … |
| --ink-heading | tokens.css | … |
| --ink-muted | tokens.css | … |
| --line | tokens.css | … |
| --line-brand-strong | tokens.css | … |
| --line-input | tokens.css | … |
| --r-md | tokens.css | … |
| --r-sm | tokens.css | … |
| --recess-fill | tokens.css | … |
| --rgb-white | tokens.css | … |
| --shadow-hairline-card | tokens.css | … |
| --shadow-recess | tokens.css | … |
| --surface-solid | tokens.css | … |
| --text-small | tokens.css | … |
| --wash-active | tokens.css | … |
| --wash-hover | tokens.css | … |
Accessibility
- single renders role="radiogroup" with role="radio" items and aria-checked; multiple renders role="group" with aria-pressed buttons.
- Roving tabindex: one tab stop, arrows move (Up and Down when vertical), Home and End jump to the ends.
- aria-label on the group is required; icon-only items each need their own aria-label.
Do and don't
Do
- Use multiple for independent options (bold, italic).
- Keep items to one short word or a familiar icon.
Don't
- Don't use single where a value is always required; use SegmentedControl.
For AI agents
This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.
Open toggle-group.mdRelated: toggle, tabs, button-group