Toolbar
General-purpose toolbar with start, center, and end content slots. Renders a `role="toolbar"` container with roving-tabindex keyboard navigation: the whole bar is one tab stop, and the arrow keys move between the controls inside it. The toolbar's `size` cascades through supported sizeable children and nested Toolbars so the bar's controls stay visually coordinated. A floating layer, Dialog, or Drawer starts a new cascade. Use it for contextual actions within a content area — above a table, as a card header with actions, or in a panel — not for app-wide navigation (use TopNav for that).
Examples
Section titled “Examples”Default
Section titled “Default”<Toolbar label="Actions" startContent={( <> <Button icon={Scissors} isIconOnly label="Cut" variant="ghost" /> <Button icon={Copy} isIconOnly label="Copy" variant="ghost" /> <Button label="Paste" variant="ghost" /> </> )} endContent={( <Button icon={Settings} isIconOnly label="Settings" variant="ghost" /> )}/>Three Slot
Section titled “Three Slot”<Toolbar label="Document toolbar" startContent={( <Button icon={ArrowLeft} isIconOnly label="Back" variant="ghost" /> )} centerContent={<Text type="label">Q1 Planning Document</Text>} endContent={( <> <Button label="Discard" variant="secondary" /> <Button label="Save" variant="primary" /> </> )}/>function Render() { const [tab, setTab] = useState('overview'); return ( <div className={columnStyle}> {(['sm', 'md', 'lg'] as const).map(size => ( <Toolbar dividers={['bottom']} endContent={ <> <Button icon={Download} isIconOnly label="Export" variant="ghost" /> <Button label="New item" variant="primary" /> </> } key={size} label={`Tab navigation (${size})`} size={size} startContent={ <Tabs label="Sections" onChange={setTab} value={tab}> <Tab label="Overview" value="overview" /> <Tab label="Analytics" value="analytics" /> <Tab label="Settings" value="settings" /> </Tabs> } /> ))} </div> );}Size Cascade Consumers
Section titled “Size Cascade Consumers”function Render() { const [quantity, setQuantity] = useState<number | null>(1); const [page, setPage] = useState(1); return ( <Toolbar label="Order controls" size="sm" startContent={ <> <InputGroup isLabelHidden label="Order details"> <NumberInput isLabelHidden label="Quantity" onChange={setQuantity} value={quantity} /> <Select isLabelHidden label="Unit" onChange={() => {}} options={['Each', 'Case']} value="Each" /> </InputGroup> <ToggleButton isSelected label="Pinned" /> <SplitButton items={[{label: 'Save as template'}]} label="Save" variant="primary" /> <Pagination onChange={setPage} page={page} totalPages={3} /> </> } /> );}Size Cascade Boundaries
Section titled “Size Cascade Boundaries”<Toolbar endContent={ <Popover content={ <TextInput isLabelHidden label="Overlay search" onChange={() => {}} placeholder="Defaults to md" value="" /> } label="Overlay controls" padding={3}> <Button label="Open md overlay" variant="secondary" /> </Popover> } label="Outer toolbar" size="lg" startContent={ <Toolbar label="Nested toolbar" startContent={ <> <Button label="Inherited action" /> <ToggleButton label="Inherited toggle" /> </> } /> }/>Card Header
Section titled “Card Header”<Card style={{width: 480}}> <Toolbar dividers={['bottom']} endContent={ <> <Button icon={Filter} isIconOnly label="Filter" variant="ghost" /> <Button icon={Plus} isIconOnly label="Add user" variant="primary" /> </> } label="User list actions" size="sm" startContent={<Text type="label">Users</Text>} /> <div className={cardContentStyle}> <Text type="body">Table rows go here…</Text> </div></Card>Table Filters
Section titled “Table Filters”function Render() { const [status, setStatus] = useState<string | null>(null); return ( <Toolbar endContent={ <SegmentedControl label="View" onChange={() => {}} value="list"> <SegmentedControlItem label="List" value="list" /> <SegmentedControlItem label="Grid" value="grid" /> </SegmentedControl> } label="Table filters" size="sm" startContent={ <> <TextInput isLabelHidden label="Search" onChange={() => {}} placeholder="Search…" value="" /> <Select isLabelHidden label="Status" onChange={setStatus} options={['Open', 'In progress', 'Done']} placeholder="Status" value={status} /> <Button label="Assignee" variant="secondary" /> </> } /> );}Bulk Actions
Section titled “Bulk Actions”<Toolbar label="Bulk actions" size="sm" dividers={['top', 'bottom']} startContent={( <> <Badge label="5 selected" /> <Button icon={Trash2} isIconOnly label="Delete" variant="ghost" /> <Button icon={Archive} isIconOnly label="Archive" variant="ghost" /> </> )} endContent={<Button label="Deselect all" variant="ghost" />}/>Stacked
Section titled “Stacked”<Card style={{width: 640}}> <Toolbar dividers={['bottom']} endContent={ <> <Button icon={RefreshCw} isIconOnly label="Refresh" variant="ghost" /> <Button icon={Download} isIconOnly label="Export" variant="ghost" /> <Button label="New order" variant="primary" /> </> } label="Primary actions" size="sm" startContent={<Text type="label">Orders</Text>} /> <Toolbar dividers={['bottom']} endContent={<Button label="Clear filters" variant="ghost" />} label="Filters" size="sm" startContent={ <> <TextInput isLabelHidden label="Search orders" onChange={() => {}} placeholder="Search orders…" value="" /> <Button label="Status" variant="secondary" /> <Button label="Date range" variant="secondary" /> </> } /> <div className={cardContentStyle}> <Text type="body">Order table rows…</Text> </div></Card>Vertical
Section titled “Vertical”<div style={{height: 320, display: 'inline-flex'}}> <Toolbar dividers={['end']} endContent={ <Button icon={Settings} isIconOnly label="Settings" variant="ghost" /> } label="Canvas tools" orientation="vertical" startContent={ <> <Button icon={Scissors} isIconOnly label="Cut" variant="ghost" /> <Button icon={Copy} isIconOnly label="Copy" variant="ghost" /> <Button icon={Trash2} isIconOnly label="Delete" variant="ghost" /> </> } /></div>Toolbar
Section titled “Toolbar”General-purpose toolbar with start, center, and end content slots. Renders a `role="toolbar"` container with roving-tabindex keyboard navigation: the whole bar is one tab stop, and the arrow keys move between the controls inside it. The toolbar's `size` cascades through supported sizeable children and nested Toolbars so the bar's controls stay visually coordinated. A floating layer, Dialog, or Drawer starts a new cascade. Use it for contextual actions within a content area — above a table, as a card header with actions, or in a panel — not for app-wide navigation (use TopNav for that).
| Prop | Type | Default | Description |
|---|---|---|---|
centerContent | ReactNode | — | Content centered between the start and end slots. When present, the layout switches to a three-track grid (1fr auto 1fr) so the center stays centered regardless of how wide the outer slots are. |
className | string | — | Additional CSS class names applied to the root element. |
data-testid | string | — | Test ID applied to the root element. |
dividers | ReadonlyArray<ToolbarDividerSide> | — | Which sides get a hairline divider border. |
endContent | ReactNode | — | Content aligned to the end (right in LTR). |
gap | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 1 | Gap between items within each slot, using the spacing scale. |
label* | string | — | Accessible label for the toolbar. |
orientation | "horizontal" | "vertical" | 'horizontal' | Layout and keyboard-navigation orientation. Controls which arrow keys move focus between items. |
ref | Ref<HTMLDivElement> | — | Ref forwarded to the root element. |
size | "sm" | "md" | "lg" | The enclosing Toolbar size, otherwise 'md' | Toolbar size. Supported sizeable children inherit it as their default, including nested Toolbars; Button, ButtonGroup, SplitButton, and ToggleButton; InputGroup, TextInput, NumberInput, Select, MultiSelect, AutocompleteInput, TagsInput, TextArea, and SearchFilterInput; plus SegmentedControl, Tabs, and Pagination. Floating layers, Dialogs, and Drawers start a new size cascade. |
startContent | ReactNode | — | Content aligned to the start (left in LTR). |
style | CSSProperties | — | Inline styles applied to the root element. |