XDSToolbar@xds/core · Toolbar
Usage
Toolbar is a horizontal bar with left, center, and right areas. Use it for contextual actions within a content area — above a table, inside a card, or in a panel — not as a page-level header. Set the size once on the toolbar and all buttons, inputs, and tabs inside it match automatically.Best practices
| Guidance | Practices |
|---|---|
| Do | Put secondary actions like "Back" on the left, and primary actions like "Save" on the right. |
| Do | Make temporary toolbars like bulk selection visually distinct so users can tell they're contextual — for example, with a background color or border. |
| Do | Visually separate the toolbar from the content below it — with a divider, a background variant, or both. |
| Do | Use Toolbar as a card header when the header has interactive actions like filter or add — it gives you slot layout, keyboard navigation, and size cascading. If the header is just a title with no actions, a LayoutHeader or Section is enough. |
| Don't | Put too many actions in one toolbar — move less common items into a MoreMenu. |
| Don't | Set size on individual child buttons — set it once on the toolbar and it cascades automatically. |
| Don't | Use Toolbar for app-wide navigation like main menu links or sign out — use TopNav or LayoutHeader for that. |
Import
tsimport {XDSToolbar} from '@xds/core/Toolbar'
Props
| Prop | Type | Description |
|---|---|---|
labelrequired | string | Accessible label for the toolbar, applied as aria-label. |
startContent | ReactNode | Content aligned to the start (left in LTR). |
centerContent | ReactNode | Centered content. Switches layout to CSS grid (1fr auto 1fr). |
endContent | ReactNode | Content aligned to the end (right in LTR). |
density | 'compact' | 'default' (default: 'default') | Toolbar density. Controls minimum height. |
gap | SpacingStep (default: 2) | Gap between items within each slot. |
orientation | 'horizontal' | 'vertical' (default: 'horizontal') | Orientation for keyboard navigation. Controls arrow key direction. |
variant | XDSSectionVariant (default: 'transparent') | Visual variant passed to XDSSection. |
xstyle | StyleXStyles | StyleX styles for layout customization. Must be a stylex.create() value. |
Sub-components
Toolbar is a compound component with 1 sub-component.XDSToolbar
General-purpose toolbar container with three content slots and roving tabindex.| Prop | Type | Description |
|---|---|---|
labelrequired | string | Accessible label for the toolbar, applied as aria-label. |
startContent | ReactNode | Content aligned to the start (left in LTR). |
centerContent | ReactNode | Centered content. Switches layout to CSS grid (1fr auto 1fr). |
endContent | ReactNode | Content aligned to the end (right in LTR). |
density | 'compact' | 'default' (default: 'default') | Toolbar density. Controls minimum height. |
gap | SpacingStep (default: 2) | Gap between items within each slot. |
orientation | 'horizontal' | 'vertical' (default: 'horizontal') | Orientation for keyboard navigation. Controls arrow key direction. |
variant | XDSSectionVariant (default: 'transparent') | Visual variant passed to XDSSection. |
xstyle | StyleXStyles | StyleX styles for layout customization. Must be a stylex.create() value. |
Examples
Common configurations, variations, and states.Toolbar — Bulk ActionsA compact toolbar with the wash variant for showing bulk selection actions. Use when the user selects multiple items in a list or table and needs quick access to batch operations.
tsx'use client';import {useState} from 'react';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSBadge} from '@xds/core/Badge';import {XDSTable} from '@xds/core/Table';import {useXDSTableSelection, useXDSTableSelectionState} from '@xds/core/Table';import {TrashIcon, ArchiveBoxIcon} from '@heroicons/react/24/outline';const DATA = [{id: '1', name: 'Alex Johnson', status: 'Active', role: 'Admin'},{id: '2', name: 'Sam Rivera', status: 'Active', role: 'Editor'},{id: '3', name: 'Jordan Lee', status: 'Invited', role: 'Viewer'},{id: '4', name: 'Taylor Kim', status: 'Active', role: 'Editor'},{id: '5', name: 'Casey Park', status: 'Active', role: 'Viewer'},];export default function ToolbarBulkActions() {const [selectedKeys, setSelectedKeys] = useState<Set<string>>(() => new Set(['1', '3', '5']),);const {selectionConfig} = useXDSTableSelectionState({data: DATA,idKey: 'id',selectedKeys,setSelectedKeys,});const selectionPlugin = useXDSTableSelection(selectionConfig);return (<>{selectedKeys.size > 0 && (<XDSToolbarlabel="Bulk actions"size="sm"variant="wash"startContent={<><XDSBadge label={`${selectedKeys.size} selected`} /><XDSButtonlabel="Delete"variant="ghost"icon={<XDSIcon icon={TrashIcon} />}isIconOnly/><XDSButtonlabel="Archive"variant="ghost"icon={<XDSIcon icon={ArchiveBoxIcon} />}isIconOnly/></>}endContent={<XDSButtonlabel="Deselect all"variant="ghost"onClick={() => setSelectedKeys(new Set())}/>}/>)}<XDSTableidKey="id"columns={[{key: 'name', header: 'Name'},{key: 'status', header: 'Status'},{key: 'role', header: 'Role'},]}data={DATA}plugins={{selection: selectionPlugin}}/></>);}
Toolbar — Card Header
tsx'use client';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSHeading} from '@xds/core/Text';import {XDSCard} from '@xds/core/Card';import {XDSSection} from '@xds/core/Section';import {FunnelIcon, PlusIcon} from '@heroicons/react/24/outline';import * as stylex from '@stylexjs/stylex';const styles = stylex.create({card: {width: 600,height: '100%',marginTop: 260,},});export default function ToolbarCardHeader() {return (<XDSCard xstyle={styles.card}><XDSToolbarlabel="User list actions"size="sm"dividers={['bottom']}startContent={<XDSHeading level={4}>Card title</XDSHeading>}endContent={<><XDSButtonlabel="Filter"variant="ghost"icon={<XDSIcon icon={FunnelIcon} />}isIconOnly/><XDSButtonlabel="Add user"icon={<XDSIcon icon={PlusIcon} />}isIconOnly/></>}/><XDSSection /></XDSCard>);}
Toolbar — Sizes
tsx'use client';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSHeading} from '@xds/core/Text';import {XDSStack} from '@xds/core/Layout';import {XDSCard} from '@xds/core/Card';import {FunnelIcon, PlusIcon} from '@heroicons/react/24/outline';import * as stylex from '@stylexjs/stylex';const styles = stylex.create({container: {width: 600,},});const SIZES = [{size: 'sm' as const, label: 'Small'},{size: 'md' as const, label: 'Medium'},{size: 'lg' as const, label: 'Large'},];export default function ToolbarSizes() {return (<XDSStack direction="vertical" gap={4} xstyle={styles.container}>{SIZES.map(({size, label}) => (<XDSCard key={size}><XDSToolbarlabel={`${label} toolbar`}size={size}dividers={['bottom']}startContent={<XDSHeading level={4}>{label}</XDSHeading>}endContent={<><XDSButtonlabel="Filter"variant="ghost"icon={<XDSIcon icon={FunnelIcon} />}isIconOnly/><XDSButton label="Add" icon={<XDSIcon icon={PlusIcon} />} /></>}/></XDSCard>))}</XDSStack>);}
Toolbar — Tab NavigationA toolbar with tabs in the start slot and an action button at the end. Use as a card or section header when content is split into tabs with a primary action alongside.
tsx'use client';import {useState} from 'react';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSTabList, XDSTab} from '@xds/core/TabList';import {XDSCard} from '@xds/core/Card';import {XDSSection} from '@xds/core/Section';import {PlusIcon} from '@heroicons/react/24/outline';import * as stylex from '@stylexjs/stylex';const styles = stylex.create({card: {width: '100%',height: '100%',marginTop: 200,},});export default function ToolbarWithTabs() {const [tab, setTab] = useState('overview');return (<XDSCard xstyle={styles.card}><XDSToolbarlabel="Section navigation"dividers={['bottom']}startContent={<XDSTabList value={tab} onChange={setTab}><XDSTab value="overview" label="Overview" /><XDSTab value="analytics" label="Analytics" /><XDSTab value="settings" label="Settings" /></XDSTabList>}endContent={<XDSButtonlabel="New item"icon={<XDSIcon icon={PlusIcon} />}isIconOnly/>}/><XDSSection /></XDSCard>);}
Toolbar — Table FilterA compact toolbar with a search input, filter buttons, and an overflow menu. Use above a data table to let users search, filter, and access view options.
tsx'use client';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSTextInput} from '@xds/core/TextInput';import {XDSMoreMenu} from '@xds/core/MoreMenu';import {XDSStack} from '@xds/core/Layout';import {XDSTable} from '@xds/core/Table';import * as stylex from '@stylexjs/stylex';import {MagnifyingGlassIcon,ChevronDownIcon,} from '@heroicons/react/24/outline';const styles = stylex.create({container: {width: 600,},});export default function ToolbarTableFilter() {return (<XDSStack direction="vertical" xstyle={styles.container}><XDSToolbarlabel="Table filters"size="sm"dividers={['bottom']}startContent={<><XDSTextInputlabel="Search"isLabelHiddenplaceholder="Search..."value=""onChange={() => {}}startIcon={MagnifyingGlassIcon}/><XDSButtonlabel="Status"variant="secondary"endContent={<XDSIcon icon={ChevronDownIcon} />}/><XDSButtonlabel="Priority"variant="secondary"endContent={<XDSIcon icon={ChevronDownIcon} />}/></>}endContent={<XDSMoreMenuitems={[{label: 'Compact view'},{label: 'Comfortable view'},{label: 'Export CSV'},]}/>}/><XDSTableidKey="id"columns={[{key: 'task', header: 'Task'},{key: 'status', header: 'Status'},{key: 'priority', header: 'Priority'},]}data={[{id: '1', task: 'Fix login bug', status: 'Open', priority: 'High'},{id: '2',task: 'Update docs',status: 'In progress',priority: 'Medium',},{id: '3', task: 'Add unit tests', status: 'Open', priority: 'Low'},]}/></XDSStack>);}
Showcase source
tsx'use client';import {XDSToolbar} from '@xds/core/Toolbar';import {XDSButton} from '@xds/core/Button';import {XDSIcon} from '@xds/core/Icon';import {XDSHeading} from '@xds/core/Text';import {XDSCard} from '@xds/core/Card';import {XDSSection} from '@xds/core/Section';import {ArrowLeftIcon} from '@heroicons/react/24/outline';import * as stylex from '@stylexjs/stylex';const styles = stylex.create({card: {width: 600,height: '100%',marginTop: 260,},});export default function ToolbarThreeSlot() {return (<XDSCard xstyle={styles.card}><XDSToolbarlabel="Document toolbar"dividers={['bottom']}startContent={<XDSButtonlabel="Back"variant="ghost"icon={<XDSIcon icon={ArrowLeftIcon} />}isIconOnly/>}centerContent={<XDSHeading level={4}>Title</XDSHeading>}endContent={<><XDSButton label="Discard" variant="secondary" /><XDSButton label="Save" variant="primary" /></>}/><XDSSection /></XDSCard>);}