ToggleGroup
A pill container of toggle buttons that act like a radio group (single select) or a multi-select toolbar, built on Base UI's ToggleGroup primitive.
Playground
Installation
pnpm add @tessinaui/uiUsage
import { ToggleGroup, ToggleGroupItem } from "@tessinaui/ui";<ToggleGroup variant="outline" size="md" defaultValue={["left"]}>
<ToggleGroupItem value="left" leadingIcon={<AlignLeft />} label="Left" />
<ToggleGroupItem value="center" leadingIcon={<AlignCenter />} label="Center" />
<ToggleGroupItem value="right" leadingIcon={<AlignRight />} label="Right" />
</ToggleGroup>Showcase
Variants, intents, sizes, orientations, single-vs-multiple, usage patterns, and RTL:
API Reference
ToggleGroup Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "outline" | "ghost" | "outline" | Visual style applied to all items |
intent | "none" | "error" | "none" | Semantic color intent applied to all items |
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Size applied to all items |
rounded | "full" | "lg" | "md" | "sm" | "none" | "full" | Corner radius applied to both the container and every item |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction of the group |
gap | "micro" | "none" | "micro" | Gap between items — micro is 4px (horizontal) / 8px (vertical), none is 0px |
multiple | boolean | false | When true, multiple items can be pressed at once; when false, at most one item is pressed |
value | string[] | — | Controlled array of pressed item values |
defaultValue | string[] | [] | Initial pressed values for uncontrolled usage |
onValueChange | (value: string[], event: Event) => void | — | Callback fired when the pressed set changes |
loopFocus | boolean | true | Whether arrow-key focus wraps around the group |
disabled | boolean | false | Disables every item in the group at once |
dir | "ltr" | "rtl" | "ltr" | Text direction — RTL reverses icon/label order inside each item |
ToggleGroupItem Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Required. Identifier used in the group's value array when the item is pressed |
label | string | — | Visible label text |
leadingIcon | React.ReactNode | — | Icon rendered before the label; replaced by a spinner when loading |
trailingIcon | React.ReactNode | — | Icon rendered after the label; hidden when loading |
loading | boolean | false | Shows a spinner and disables this item |
disabled | boolean | false | Disables this item individually |
aria-label | string | — | Accessible label (required when no visible label is provided) |
Single vs Multiple
By default ToggleGroup is single-select (multiple={false}) — it behaves like a radio group, pressing a new item unpresses the previous one. The value prop is still an array so both modes share one shape:
// Single select — only one pressed value at a time
const [align, setAlign] = useState<string[]>(["left"]);
<ToggleGroup value={align} onValueChange={setAlign}>
<ToggleGroupItem value="left" leadingIcon={<AlignLeft />} />
<ToggleGroupItem value="center" leadingIcon={<AlignCenter />} />
<ToggleGroupItem value="right" leadingIcon={<AlignRight />} />
</ToggleGroup>Set multiple to let users press any combination:
// Multi select — each item toggles independently
const [format, setFormat] = useState<string[]>([]);
<ToggleGroup multiple value={format} onValueChange={setFormat}>
<ToggleGroupItem value="bold" leadingIcon={<Bold />} />
<ToggleGroupItem value="italic" leadingIcon={<Italic />} />
<ToggleGroupItem value="underline" leadingIcon={<Underline />} />
</ToggleGroup>Supported Combinations
| Variant | Intents |
|---|---|
outline | none, error |
ghost | none, error |
Sizes
| Size | Height | Use case |
|---|---|---|
xs | 40px | Compact toolbars |
sm | 48px | Secondary actions |
md | 56px | Default, most use cases |
lg | 64px | Prominent toolbars |
xl | 104px | Hero / large controls |
Accessibility
The ToggleGroup component:
- Built on Base UI's
ToggleGroup+Toggleprimitives - Renders a
role="group"container witharia-orientationreflecting theorientationprop - Each item renders a
<button>witharia-pressedreflecting its pressed state - Keyboard: Tab focuses the group, Arrow keys move focus between items (with optional wrap via
loopFocus), Enter / Space toggles the focused item data-pressed,data-disabled, anddata-focus-visibleattributes expose state for CSS- Focus ring meets WCAG 2.1 AA on each item (2px ring + 2px offset)
- Touch targets ≥ 44×44px for xs/sm; larger sizes exceed minimum
loadingsetsaria-busy="true"and disables the itemdisabled(item or group) setspointer-events-noneand the nativedisabledattribute- RTL fully supported via the
dirprop
ToggleButton
A button that toggles between on and off states, with the same variant, intent, size, and rounded system as Button. Shows a persistent pressed visual when active.
Toolbar
Container for grouping a set of controls — buttons, toggles, links, inputs, separators. Wraps `@base-ui/react/toolbar` for keyboard focus management. Four variants, three sizes, five rounded values, horizontal (with overflow wrap) + vertical orientation, LTR/RTL.