Actions
Toolbar
A labelled strip of controls that share one tab stop.
When to use it: Use it when several related controls would otherwise each cost a Tab press.
Example
import { ToggleButton, ToggleButtonGroup } from "@comp0/react";
import { Toolbar } from "@comp0/react";
import { BoldIcon, ItalicIcon, UnderlineIcon } from "@heroicons/react/16/solid";
export function Example() {
return (
<Toolbar
aria-label="Text formatting"
className="flex items-center gap-2 rounded border border-zinc-950/10 p-1.5 dark:border-white/10"
>
<ToggleButtonGroup
type="multiple"
defaultValue={["bold"]}
aria-label="Text style"
className="flex gap-1"
>
<ToggleButton
value="bold"
aria-label="Bold"
className="rounded px-3 py-2.5 text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
<BoldIcon className="size-4" aria-hidden="true" />
</ToggleButton>
<ToggleButton
value="italic"
aria-label="Italic"
className="rounded px-3 py-2.5 text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
<ItalicIcon className="size-4" aria-hidden="true" />
</ToggleButton>
<ToggleButton
value="underline"
aria-label="Underline"
className="rounded px-3 py-2.5 text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
<UnderlineIcon className="size-4" aria-hidden="true" />
</ToggleButton>
</ToggleButtonGroup>
<span aria-hidden="true" className="h-6 w-px bg-zinc-950/10 dark:bg-white/10" />
<ToggleButtonGroup
type="single"
defaultValue="left"
aria-label="Alignment"
className="flex gap-1"
>
<ToggleButton
value="left"
className="rounded px-3 py-2.5 text-base text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 sm:text-sm dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
Left
</ToggleButton>
<ToggleButton
value="center"
className="rounded px-3 py-2.5 text-base text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 sm:text-sm dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
Center
</ToggleButton>
<ToggleButton
value="right"
className="rounded px-3 py-2.5 text-base text-zinc-950 data-selected:bg-teal-100 data-selected:text-teal-950 sm:py-2 sm:text-sm dark:text-zinc-50 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50"
>
Right
</ToggleButton>
</ToggleButtonGroup>
</Toolbar>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
Toolbar
Row of controls that shares one tab stop; arrow keys move between them. Owns a DOM element.
ToggleButtonGroupOptional
Optional selection group inside the toolbar; it announces the relationship and can manage which values are on. Owns a DOM element.
ToggleButtonOptional
Native button that owns one press target. Owns a DOM element.
Step by step
- 1
Add the main part
Wrap the controls in Toolbar and give it an aria-label.
- 2
Add the supporting parts
Group related toggles in ToggleButtonGroup so their relationship is announced.
- 3
Make the behavior clear
Pick orientation to match the layout; arrow keys follow it automatically.
Exampletsx <Toolbar aria-label="Text formatting"><ToggleButtonGroup type="multiple" aria-label="Text style"><ToggleButton value="bold">Bold</ToggleButton></ToggleButtonGroup></Toolbar>
Keyboard
- ⇥
- Moves into the toolbar to the last-used control; Tab again leaves.
- →
- Moves to the next control without wrapping. · horizontal
- ←
- Moves to the previous control without wrapping. · horizontal
- ↓
- Moves to the next control. · vertical
- ↑
- Moves to the previous control. · vertical
- Home
- Moves to the first control.
- End
- Moves to the last control.
- ↵
- Presses the focused control.
- Space
- Presses the focused control.
Forms and accessibility
A toolbar does not create form values; its controls submit their own.
Accessibility checklist
- Give the toolbar an aria-label that names the task, such as Text formatting.
- Keep controls in a visual order that matches the arrow-key order.
- Nested composites like a listbox or menu keep their own arrow keys; do not double-handle them.
API reference
import { Toolbar, ToggleButton, ToggleButtonGroup } from "@comp0/react";Toolbar
DOM elementRow of controls that shares one tab stop; arrow keys move between them.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Names the toolbar for assistive technology. |
orientation | "horizontal" | "vertical" | Arrow-key direction, announced via aria-orientation; defaults to "horizontal". |
ToggleButtonGroup
OptionalDOM elementOptional selection group inside the toolbar; it announces the relationship and can manage which values are on.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Names the group for assistive technology. |
type | "single" | "multiple" | Whether the group keeps one value or many. |
value | string | string[] | Controlled selection: a string for single, a string[] for multiple. |
defaultValue | string | string[] | Initial selection: a string for single, a string[] for multiple. |
onChange | (value: string | string[]) => void | Receives the next selection; "" when a single group empties. |
ToggleButton
OptionalDOM elementNative button that owns one press target.
| Prop | Type | Description |
|---|---|---|
value | string | Identifies the button inside a selection-managing group. |
disabled | boolean | Removes the button from the toolbar's arrow-key order. |
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
[data-orientation]on Toolbar
- The arrow-key direction.
[data-selected]on ToggleButton
- The button is on.