Toolbar
The Toolbar component provides a canvas-style icon toolbar with support for orientations, active states, animated context switching, separators, fan-out sub-panels, and drag & drop onto surfaces, and headed drawers of labeled tiles.
Toolbar belongs to the Advanced React capability profile — a specialized, React-only surface with no Pixi dependency, despite its canvas-adjacent purpose.
Toolbar is not a default page action row. It is built for a canvas/tool-palette interaction — active tools, groups, slots, folders, and fan-out panels — not for an ordinary page’s list of commands. DataPage’s built-in action row renders ActionMenubar (from @cratis/components/Common), not Toolbar. Reach for ActionMenubar, or a product-owned action row, for flat page-level actions; reach for Toolbar only when the surface is genuinely a spatial tool palette. See Choosing a component: Actions and tool palettes.
Pass React icon nodes or product-owned SVGs for a dependency-free toolbar. Consumer-owned icon-font class strings remain accepted, but Components does not install an icon font or infer provider base classes; the product must load the matching stylesheet and pass the complete class string.
Import every Toolbar component from its subpath:
import { Toolbar, ToolbarButton } from '@cratis/components/Toolbar';Keyboard and accessibility
Section titled “Keyboard and accessibility”- The root renders
role='toolbar',aria-orientation, and an accessible name. The name falls back to the provider’smessages.toolbar.label, thenTools; passaria-labeloraria-labelledbyto name each toolbar. focusModedefaults toToolbarFocusMode.Arrows: Up/Down move between tools in the default vertical orientation; a horizontal toolbar uses Left/Right (reversed in RTL). Home/End move to the first/last available tool in DOM order. Navigation skips disabled, hidden, and inert tools and stops at either end; it does not wrap. Each tool remains its own Tab stop, so Tab and Shift+Tab work as before.- Set
focusMode={ToolbarFocusMode.SingleTabStop}for the WAI-ARIA toolbar pattern: the toolbar’s own tools (ToolbarButton, folder and fan-out triggers) share one Tab stop, which starts at the first available tool, follows the arrow keys, and returns to the last focused tool. When that tool is disabled, hidden, or removed, the Tab stop moves to the first available tool. A tool rendered outside the toolbar’s own markup, such as through a portal or inside a nested element withrole="toolbar", keeps its own Tab stop. Tools in an open folder or fan-out panel belong to the same Tab stop, so you reach them with the arrow keys rather than Tab. Controls you place in the toolbar yourself, widgets such as inputs and sliders, aToolbarButtonwith an explicitpt.root.tabIndex, and a folder or fan-out trigger with an explicitpt.trigger.tabIndexkeep their own Tab stop; with a tab index of 0 or higher the arrow keys still reach them, while-1removes the tool from both Tab and arrow-key navigation. Until the toolbar has chosen its active tool (for example, in server-rendered markup before hydration), every tool keeps its own Tab stop. - Set
focusMode={ToolbarFocusMode.None}to keep native Tab behavior without toolbar key handling. ImportToolbarFocusModefrom@cratis/components/Toolbar.SingleTabStopbecomes the default in the next major release (#353). - Arrows and Home/End inside inputs, sliders, selects, and custom widgets retain their own behavior. Nested toolbars handle their own keys. Key handlers on a tool or
pt.rootcan cancel navigation withpreventDefault()orstopPropagation(). titleis required onToolbarButtonandToolbarFolder, andtooltiponToolbarFanOutItem. That text becomes the button’saria-labeland its tooltip, which appears on hover and on keyboard focus.- Passing
activesetsaria-pressedtotrueorfalseas well as the visual state (data-active,data-selected); omittingactiveleaves it unset. See Active state. - Folder and fan-out triggers expose
aria-expandedandaria-controls. Their panels close on Escape or a pointer press outside, return focus to their trigger after Escape, and areinertandaria-hiddenwhile collapsed. - Toolbar, folder, fan-out, and context transitions are suppressed under
prefers-reduced-motion: reduce.
Components
Section titled “Components”| Component | Description |
|---|---|
Toolbar | Container that groups toolbar buttons into a pill-shaped bar |
ToolbarButton | Button that renders non-empty text or otherwise an icon, with a hover tooltip |
ToolbarSeparator | Visual divider that separates groups of buttons |
ToolbarSection | Section within a toolbar that animates between named contexts |
ToolbarContext | Named context (set of buttons) inside a ToolbarSection |
ToolbarFanOutItem | Button that slides out a horizontal sub-panel on click |
ToolbarFolder | Button that reveals a dynamically sized grid of buttons on click |
ToolbarGroup | Logical sub-group of toolbar items, rendered as its own pill with a gap between adjacent groups |
ToolbarSlotProvider | Context provider that enables the slot system — wrap the application root or a feature boundary |
ToolbarSlot | Renders nothing itself; injects its children into the named slot at the given order position |
ToolbarLayout | Named layout boundary that swaps default content for matching slot content |
Stable composition and measurement parts
Section titled “Stable composition and measurement parts”Deeply styled products should measure and select Toolbar structure through typed pt surfaces and data-cratis-part, not implementation class names.
| Component | Type | pt key → data-cratis-part |
|---|---|---|
Toolbar | ToolbarParts | root → root |
ToolbarButton | ToolbarButtonParts | root → button; icon → icon; label → label |
ToolbarGroup | ToolbarGroupParts | root → toolbar-group; slot → toolbar-slot; incoming → toolbar-slot-incoming; outgoing → toolbar-slot-outgoing |
ToolbarSeparator | ToolbarSeparatorParts | root → toolbar-separator |
ToolbarLayout | ToolbarLayoutParts | root → toolbar-layout; slot → toolbar-slot; incoming → toolbar-slot-incoming; outgoing → toolbar-slot-outgoing |
ToolbarSection | ToolbarSectionParts | root → toolbar-section; context → toolbar-context |
ToolbarFolder | ToolbarFolderParts | root → toolbar-folder; trigger → toolbar-folder-trigger; panel → toolbar-folder-panel; drawer: drawerHeader, drawerTitle, drawerClose, tile, tileIcon, tileLabel (see Headed drawer) |
ToolbarFanOutItem | ToolbarFanOutParts | root → fanout-root; trigger → fanout-trigger; panel → fanout-panel |
The active tool, active context, and an open folder or fan-out also carry the canonical data-selected or data-open state. Contexts expose data-context-name and data-active; sections and slots expose data-transitioning. Folder and fan-out panels expose data-expanded and data-direction; fan-out also exposes data-settled, while folders expose data-mode. Collapsed/inactive panels and contexts are inert so hidden tools do not remain in keyboard navigation.