Toolbar
A row of related controls, such as the formatting buttons of an editor, that takes one Tab stop. The arrow keys move between them.
Installation
Set up Camaleo once (Installation), then import what you need. It renders on the client.
import { Toolbar, ToolbarGroup, ToolbarButton, ToolbarToggle, ToolbarLink, ToolbarInput, ToolbarSeparator } from "@camaleo/react";Anatomy
A div with role="toolbar". Only one control in it is in the Tab order at a time; the arrow keys move that spot. A ToggleGroup inside joins the same order when its toggles render through ToolbarButton.
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above. Click into one, then use Tab and the arrow keys.
- #4821Padaria Estrela$186.40
- #4822Café Aurora$92.00
- #4823Mercado Sol$412.75
Actions for selected rows
Select orders and press Export. The search field sits next to the toolbar, not inside it: it searches the table, not the selection, so it keeps its own Tab stop.
Vertical tool palette
With orientation="vertical" the Up and Down arrows move focus. The tools are a ToggleGroup, so only one is pressed at a time.
Icon buttons with names
Every icon-only button needs an aria-label. A tooltip with the same words shows that name to sighted people too.
Overflow into More
Narrow the window. Under 420 px only Reply and Reply all stay; everything else moves into the More menu instead of wrapping.
Disabled but still reachable
Disabled toolbar buttons stay in the arrow-key order, so people find Undo and hear why it is off. Pass focusableWhenDisabled={false} to skip one.
A field inside the toolbar
Type a page number and press Enter. ToolbarInput joins the arrow-key order; inside it the arrows move the caret and leave the field only at either end of the text.
Links next to buttons
ToolbarLink goes to another page and ToolbarButton acts on this one; both share the same arrow-key order.
In context
These are whole pieces of UI you can copy, in the skin you picked.
- Contracts—
- invoice-0326.pdf182 KB
- price-list-april.xlsx48 KB
- storefront.jpg2.4 MB
Guidelines
History, formatting and insert each get a ToolbarGroup with a name, split by separators.
Bold next to Undo next to Image: people scan the whole row every time.
Bold and Undo are known by their icons. "Levels" and "Vignette" are not.
Screen readers hear the names, but everyone else has to guess, or hover each one.
Props
ToolbarToggle takes pressed and is controlled: flip it in onClick. ToolbarButton takes disabled and focusableWhenDisabled (default true). ToolbarGroup takes disabled and an aria-label. ToolbarInput takes the props of <input>; name it with aria-label.
Styling hooks
Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the toolbar itself.
Attributes
Tokens it reads
Color
Shape & size
Type & motion
This component only
/* bigger targets in the drawing app */
.canvas-tools [data-slot="toolbar"] {
--cml-toolbar-btn-size: 2.5rem;
}Accessibility
- Name every toolbar with aria-label ("Text formatting") and every ToolbarGroup or ToggleGroup that holds a set ("Alignment").
- ToolbarToggle sets aria-pressed, so screen readers hear "Bold, toggle button, pressed". Keep the label the same in both states.
- Disabled buttons stay in the arrow-key order with aria-disabled, so people still find them. Say why with aria-describedby.
- Name a ToolbarInput with aria-label. A field that serves the whole page, such as a search, reads better next to the toolbar, with its own Tab stop.