Skip to content
CraftDocs
GitHub
Home
Home
Changelog
What's New
Guide
Guide
Getting Started
Principles
Styling Components
Theme System
Foundations
All Tokens
Color
Elevation
Icons
Motion
Shape
Spacing
Typography
Libraries
Libraries
@xds/cli
@xds/core
Themes
Themes
Theme: daily
Default Theme
Theme: matcha
Neutral Theme
Components
Components
AppShell
AspectRatio
Avatar
Avatar
AvatarStatusDot
Badge
Banner
Breadcrumbs
BreadcrumbItem
Breadcrumbs
Button
Button
IconButton
ToggleButton
ToggleButtonGroup
Calendar
Card
Carousel
Chat
ChatComposer
ChatComposerDrawer
ChatComposerInput
ChatComposerTokenElement
ChatDictationButton
ChatLayout
ChatLayoutScrollButton
ChatMessage
ChatMessageBubble
ChatMessageList
ChatMessageMetadata
ChatSendButton
ChatSystemMessage
ChatTokenizedText
ChatToolCalls
Checkbox
CheckboxInput
CheckboxList
CheckboxListItem
ClickableCard
Code
CodeBlock
Collapsible
Collapsible
CollapsibleGroup
useXDSCollapsible
CommandPalette
CommandPalette
CommandPaletteEmpty
CommandPaletteFooter
CommandPaletteGroup
CommandPaletteInput
CommandPaletteItem
CommandPaletteList
DateInput
Dialog
AlertDialog
Dialog
DialogHeader
useXDSImperativeAlertDialog
useXDSImperativeDialog
Divider
DropdownMenu
DropdownMenu
DropdownMenuDivider
DropdownMenuItem
DropdownMenuItemData
DropdownMenuSection
EmptyState
Field
Field
FieldLabel
FieldStatus
Heading
HoverCard
Icon
Kbd
Layout
Center
FormLayout
Grid
GridSpan
HStack
Layout
LayoutContainer
LayoutContent
LayoutFooter
LayoutHeader
LayoutPanel
Section
StackItem
VStack
Link
List
List
ListItem
Markdown
MetadataList
MetadataList
MetadataListItem
MobileNav
MoreMenu
NavIcon
NavMenuItem
NumberInput
OverflowList
Pagination
Popover
PowerSearch
ProgressBar
Radio
RadioList
RadioListItem
Resizable
ResizeHandle
useXDSResizable
SegmentedControl
SegmentedControl
SegmentedControlItem
SelectableCard
Selector
MultiSelector
Selector
SelectorOption
SideNav
SideNav
SideNavCollapseButton
SideNavHeading
SideNavItem
SideNavSection
Skeleton
Slider
Spinner
StatusDot
Switch
Table
BaseTable
Table
TableCell
TableHeaderCell
TableRow
useXDSTableColumnSettings
useXDSTablePagination
useXDSTableSelection
useXDSTableSelectionState
useXDSTableSortable
Tabs
Tab
TabList
TabMenu
Text
TextArea
TextInput
Thumbnail
TimeInput
Timestamp
Toast
Toast
useXDSToast
Token
Tokenizer
Toolbar
Tooltip
TopNav
TopNav
TopNavHeading
TopNavItem
TopNavMegaMenu
TopNavMegaMenuFeaturedCard
TopNavMegaMenuItem
TopNavMenu
TreeList
Typeahead
BaseTypeahead
Typeahead
TypeaheadItem
useXDSHoverCard
useXDSPopover
useXDSTooltip
Utilities
Utilities
LinkProvider
MediaTheme
SyntaxTheme
Theme
useClickableContainer
useEntryAnimation
useFocusTrap
useGridFocus
useImageMode
useInputContainer
useListFocus
useMediaQuery
useOverflow
useScrollLock
useScrollOverflow
useXDSLayer
useXDSStreamingText
Terms of UsePrivacy Policy
Type to search
↑↓Navigate↵SelectEscClose
Toolbar@xds/core · XDSToolbar v0.0.13

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.
ts
import {XDSToolbar} from '@xds/core/Toolbar'

Best practices

GuidancePractices
DoPut secondary actions like "Back" on the left, and primary actions like "Save" on the right.
DoMake temporary toolbars like bulk selection visually distinct so users can tell they're contextual — for example, with a background color or border.
DoVisually separate the toolbar from the content below it — with a divider, a background variant, or both.
DoUse 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'tPut too many actions in one toolbar — move less common items into a MoreMenu.
Don'tSet size on individual child buttons — set it once on the toolbar and it cascades automatically.
Don'tUse Toolbar for app-wide navigation like main menu links or sign out — use TopNav or LayoutHeader for that.

Sub-components

Toolbar is a compound component with 1 sub-component.

XDSToolbar

General-purpose toolbar container with three content slots and roving tabindex.
PropTypeDescription
labelrequired
stringAccessible label for the toolbar, applied as aria-label.
startContent
ReactNodeContent aligned to the start (left in LTR).
centerContent
ReactNodeCentered content. Switches layout to CSS grid (1fr auto 1fr).
endContent
ReactNodeContent 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
StyleXStylesStyleX 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 && (
<XDSToolbar
label="Bulk actions"
size="sm"
variant="wash"
startContent={
<>
<XDSBadge label={`${selectedKeys.size} selected`} />
<XDSButton
label="Delete"
variant="ghost"
icon={<XDSIcon icon={TrashIcon} />}
isIconOnly
/>
<XDSButton
label="Archive"
variant="ghost"
icon={<XDSIcon icon={ArchiveBoxIcon} />}
isIconOnly
/>
</>
}
endContent={
<XDSButton
label="Deselect all"
variant="ghost"
onClick={() => setSelectedKeys(new Set())}
/>
}
/>
)}
<XDSTable
idKey="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}>
<XDSToolbar
label="User list actions"
size="sm"
dividers={['bottom']}
startContent={<XDSHeading level={4}>Card title</XDSHeading>}
endContent={
<>
<XDSButton
label="Filter"
variant="ghost"
icon={<XDSIcon icon={FunnelIcon} />}
isIconOnly
/>
<XDSButton
label="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}>
<XDSToolbar
label={`${label} toolbar`}
size={size}
dividers={['bottom']}
startContent={<XDSHeading level={4}>{label}</XDSHeading>}
endContent={
<>
<XDSButton
label="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}>
<XDSToolbar
label="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={
<XDSButton
label="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}>
<XDSToolbar
label="Table filters"
size="sm"
dividers={['bottom']}
startContent={
<>
<XDSTextInput
label="Search"
isLabelHidden
placeholder="Search..."
value=""
onChange={() => {}}
startIcon={MagnifyingGlassIcon}
/>
<XDSButton
label="Status"
variant="secondary"
endContent={<XDSIcon icon={ChevronDownIcon} />}
/>
<XDSButton
label="Priority"
variant="secondary"
endContent={<XDSIcon icon={ChevronDownIcon} />}
/>
</>
}
endContent={
<XDSMoreMenu
items={[
{label: 'Compact view'},
{label: 'Comfortable view'},
{label: 'Export CSV'},
]}
/>
}
/>
<XDSTable
idKey="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}>
<XDSToolbar
label="Document toolbar"
dividers={['bottom']}
startContent={
<XDSButton
label="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>
);
}