XDSCommandPalette@xds/core · CommandPalette
Preview coming soon

Usage

CommandPalette is a searchable dialog for quick access to commands, navigation, and actions. Use it as a keyboard-driven launcher powered by XDSSearchSource for filtering and selection.

Best practices

GuidancePractices
DoProvide a searchSource with bootstrap results so users see useful options before typing.
DoUse auxiliaryData.group on items to automatically organize results into labeled sections.
Don'tUse CommandPalette for simple dropdowns or menus — use XDSMenu or XDSSelector for inline selections.
Don'tAdd too many groups or items — curate results to keep the palette fast and scannable.

Import

ts
import {XDSCommandPalette} from '@xds/core/CommandPalette'

Props

PropTypeDescription
isOpenrequired
booleanWhether the command palette dialog is visible.
onOpenChangerequired
(isOpen: boolean) => voidCalled when the palette visibility changes.
searchSourcerequired
XDSSearchSource<T>Search source providing items via search(query) and bootstrap(). Use createStaticSource for static lists.
input
ReactNode (default: <XDSCommandPaletteInput />)Input slot. Defaults to XDSCommandPaletteInput with standard behavior.
footer
ReactNode (default: <XDSCommandPaletteFooter />)Footer slot. Defaults to XDSCommandPaletteFooter showing keyboard hints.
renderItem
(item: T, isSelected: boolean) => ReactNodePer-item render function. Auto-grouping by auxiliaryData.group is preserved. When omitted, renders label text.
emptySearchText
ReactNode (default: 'No results')Content shown when a search query returns no results.
emptyBootstrapText
ReactNode (default: 'Type to search')Content shown when there is no search query and bootstrap() returns nothing.
value
stringControlled selected value for picker mode.
onValueChange
(value: string) => voidCalled when the selected value changes in picker mode.
label
string (default: 'Command palette')Accessible label for the command palette dialog.
width
number | string (default: 640)Width of the dialog.
maxHeight
number | string (default: 480)Maximum height of the dialog.
isInline
boolean (default: false)Renders command palette content inline without modal behavior. For documentation previews and showcases only.

Sub-components

CommandPalette is a compound component with 7 sub-components.

XDSCommandPalette

Root component. Manages open state, search, keyboard navigation, and composition slots.
PropTypeDescription
isOpenrequired
booleanWhether the command palette dialog is visible.
onOpenChangerequired
(isOpen: boolean) => voidCalled when the palette visibility changes.
searchSourcerequired
XDSSearchSource<T>Search source providing items via search(query) and bootstrap(). Use createStaticSource for static lists.
input
ReactNode (default: <XDSCommandPaletteInput />)Input slot. Defaults to XDSCommandPaletteInput with standard behavior.
footer
ReactNode (default: <XDSCommandPaletteFooter />)Footer slot. Defaults to XDSCommandPaletteFooter showing keyboard hints.
renderItem
(item: T, isSelected: boolean) => ReactNodePer-item render function. Auto-grouping by auxiliaryData.group is preserved. When omitted, renders label text.
emptySearchText
ReactNode (default: 'No results')Content shown when a search query returns no results.
emptyBootstrapText
ReactNode (default: 'Type to search')Content shown when there is no search query and bootstrap() returns nothing.
value
stringControlled selected value for picker mode.
onValueChange
(value: string) => voidCalled when the selected value changes in picker mode.
label
string (default: 'Command palette')Accessible label for the command palette dialog.
width
number | string (default: 640)Width of the dialog.
maxHeight
number | string (default: 480)Maximum height of the dialog.
isInline
boolean (default: false)Renders command palette content inline without modal behavior. For documentation previews and showcases only.

XDSCommandPaletteEmpty

Empty state display for the results area. Rendered automatically by XDSCommandPalette for no-results and no-query states.
PropTypeDescription
childrenrequired
ReactNodeMessage or content to display.

XDSCommandPaletteFooter

Footer showing keyboard navigation hints. Renders default arrow/Enter/Escape hints when no children are provided.
PropTypeDescription
children
ReactNodeCustom footer content. When omitted, renders default keyboard hints via XDSKbd.
xstyle
StyleXStylesStyleX styles for layout customization. Must be a stylex.create() value.

XDSCommandPaletteGroup

Visual grouping with a heading label. Place inside XDSCommandPaletteList.
PropTypeDescription
headingrequired
stringGroup heading text.
childrenrequired
ReactNodeXDSCommandPaletteItem children.
xstyle
StyleXStylesStyleX styles for layout customization. Must be a stylex.create() value.

XDSCommandPaletteInput

Search input slot. Auto-focuses on mount. Wires to command palette context when used inside XDSCommandPalette.
PropTypeDescription
placeholder
string (default: 'Search...')Placeholder text for the input.
hasAutoFocus
boolean (default: true)Auto-focus the input when mounted.
endContent
ReactNodeContent rendered at the trailing end of the input, after the spinner. Use for clear buttons or keyboard shortcut hints.
value
stringSearch value. When omitted inside XDSCommandPalette, reads from context.
onValueChange
(value: string) => voidCalled when search value changes. When omitted inside XDSCommandPalette, writes to context.
xstyle
StyleXStylesStyleX styles for layout customization. Must be a stylex.create() value.

XDSCommandPaletteItem

A selectable item. Accepts arbitrary children for full rendering control. Registers with context for keyboard navigation when inside XDSCommandPalette.
PropTypeDescription
valuerequired
stringUnique value for identification and selection.
childrenrequired
ReactNodeItem content — render icons, descriptions, keyboard shortcuts, etc.
onSelect
(value: string) => voidCalled when this item is selected via click or Enter.
isHighlighted
boolean (default: false)Whether this item has keyboard focus. Derived from context when inside XDSCommandPalette.
isSelected
boolean (default: false)Whether this item is selected in picker mode.
isDisabled
boolean (default: false)Whether the item is non-interactive.
xstyle
StyleXStylesStyleX styles for layout customization. Must be a stylex.create() value.

XDSCommandPaletteList

Scrollable results container. Renders as a listbox for ARIA. Contains XDSCommandPaletteItem and XDSCommandPaletteGroup children.
PropTypeDescription
childrenrequired
ReactNodeItems, groups, and empty states.
label
string (default: 'Commands')Accessible label for the listbox.
xstyle
StyleXStylesStyleX styles for layout customization. Must be a stylex.create() value.

Examples

Common configurations, variations, and states.
CommandPalette — Async SearchServer-side search with loading spinner and custom empty states.
tsx
'use client';
import {useMemo} from 'react';
import {
XDSCommandPalette,
XDSCommandPaletteInput,
} from '@xds/core/CommandPalette';
import type {XDSSearchSource} from '@xds/core/Typeahead';
const allFiles = [
{id: 'readme', label: 'README.md'},
{id: 'package', label: 'package.json'},
{id: 'tsconfig', label: 'tsconfig.json'},
{id: 'index', label: 'src/index.ts'},
{id: 'app', label: 'src/App.tsx'},
];
export default function CommandPaletteAsyncSearch() {
const source = useMemo<XDSSearchSource>(
() => ({
async search(query: string) {
await new Promise(r => setTimeout(r, 400));
return allFiles.filter(f =>
f.label.toLowerCase().includes(query.toLowerCase()),
);
},
bootstrap() {
return [];
},
}),
[],
);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
input={<XDSCommandPaletteInput placeholder="Search files..." />}
emptyBootstrapText="Type a filename to search"
emptySearchText="No files found"
/>
);
}
CommandPalette — Custom FooterCommand palette with a custom footer tip message.
tsx
'use client';
import {useMemo} from 'react';
import {
XDSCommandPalette,
XDSCommandPaletteFooter,
} from '@xds/core/CommandPalette';
import {XDSText} from '@xds/core/Text';
import {createStaticSource} from '@xds/core/Typeahead';
export default function CommandPaletteCustomFooter() {
const source = useMemo(
() =>
createStaticSource([
{id: 'home', label: 'Home'},
{id: 'settings', label: 'Settings'},
]),
[],
);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
footer={
<XDSCommandPaletteFooter>
<XDSText type="supporting">Pro tip: use ⌘K to open anywhere</XDSText>
</XDSCommandPaletteFooter>
}
/>
);
}
CommandPalette — GroupedCommand palette with items grouped via auxiliaryData.group.
tsx
'use client';
import {useMemo} from 'react';
import {XDSCommandPalette} from '@xds/core/CommandPalette';
import {createStaticSource} from '@xds/core/Typeahead';
export default function CommandPaletteAutoGrouped() {
const source = useMemo(
() =>
createStaticSource([
{id: 'home', label: 'Home', auxiliaryData: {group: 'Navigation'}},
{
id: 'settings',
label: 'Settings',
auxiliaryData: {group: 'Navigation'},
},
{id: 'new-file', label: 'New File', auxiliaryData: {group: 'Actions'}},
{id: 'save', label: 'Save', auxiliaryData: {group: 'Actions'}},
]),
[],
);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
/>
);
}
CommandPalette — Picker ModeSingle-value picker with persistent selection and check indicator.
tsx
'use client';
import {useState, useMemo} from 'react';
import {XDSCommandPalette} from '@xds/core/CommandPalette';
import {XDSText} from '@xds/core/Text';
import {XDSIcon} from '@xds/core/Icon';
import {createStaticSource} from '@xds/core/Typeahead';
export default function CommandPalettePickerMode() {
const [theme, setTheme] = useState('light');
const source = useMemo(
() =>
createStaticSource([
{id: 'light', label: 'Light'},
{id: 'dark', label: 'Dark'},
{id: 'system', label: 'System'},
]),
[],
);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
value={theme}
onValueChange={setTheme}
renderItem={(item, isSelected) => (
<>
<XDSText type="body" style={{flex: 1}}>
{item.label}
</XDSText>
{isSelected && <XDSIcon icon="check" size="sm" />}
</>
)}
/>
);
}
CommandPalette — Rich ItemsCustom item rendering with icons, keyboard shortcuts, and keyword search.
tsx
'use client';
import {useMemo} from 'react';
import {XDSCommandPalette} from '@xds/core/CommandPalette';
import {XDSText} from '@xds/core/Text';
import {XDSKbd} from '@xds/core/Kbd';
import {createStaticSource} from '@xds/core/Typeahead';
import type {XDSSearchableItem} from '@xds/core/Typeahead';
type RichCommand = XDSSearchableItem<{
group?: string;
shortcut?: string;
}>;
const commands: RichCommand[] = [
{
id: 'settings',
label: 'Open Settings',
auxiliaryData: {group: 'Navigation', shortcut: 'mod+,'},
},
{
id: 'profile',
label: 'View Profile',
auxiliaryData: {group: 'Navigation'},
},
{
id: 'new-file',
label: 'Create New File',
auxiliaryData: {group: 'Actions', shortcut: 'mod+n'},
},
{
id: 'search',
label: 'Search Files',
auxiliaryData: {group: 'Actions', shortcut: 'mod+p'},
},
];
export default function CommandPaletteRichItems() {
const source = useMemo(() => createStaticSource(commands), []);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
renderItem={(item: RichCommand) => (
<>
<XDSText type="body" style={{flex: 1}}>
{item.label}
</XDSText>
{item.auxiliaryData?.shortcut && (
<XDSKbd keys={item.auxiliaryData.shortcut} />
)}
</>
)}
/>
);
}

Showcase source

tsx
'use client';
import {useMemo} from 'react';
import {XDSCommandPalette} from '@xds/core/CommandPalette';
import {createStaticSource} from '@xds/core/Typeahead';
// Remove isInline for production — command palettes should be modal.
export default function CommandPaletteShowcase() {
const source = useMemo(
() =>
createStaticSource([
{id: 'home', label: 'Home'},
{id: 'settings', label: 'Settings'},
{id: 'profile', label: 'Profile'},
{id: 'dashboard', label: 'Dashboard'},
{id: 'help', label: 'Help'},
]),
[],
);
return (
<XDSCommandPalette
isOpen
isInline
onOpenChange={() => {}}
searchSource={source}
/>
);
}