static/app/components/commandPalette/useCommandPaletteActions.mdx
import {Fragment} from 'react';
import {Button} from '@sentry/scraps/button'; import {Flex, Stack} from '@sentry/scraps/layout';
import {addSuccessMessage} from 'sentry/actionCreators/indicator'; import {toggleCommandPalette} from 'sentry/actionCreators/modal';
import * as Storybook from 'sentry/stories';
import {CommandPaletteDemo} from './stories/components';
Use CMDKAction JSX components inside your page or feature component to register contextual actions with the global command palette. Actions are registered on mount and automatically unregistered on unmount, so they only appear in the palette while your component is rendered. This is ideal for page‑specific shortcuts.
Wrap your tree in CommandPaletteProvider and place the CommandPalette UI component wherever you want the dialog to render. Then declare actions anywhere inside the provider:
to prop to navigate when selected.onAction handler to execute when selected.CMDKAction children inside another CMDKAction to show a second level. Selecting the parent reveals its children.resource prop and use the render-prop children signature to fetch and populate async results.<Storybook.Demo> <Flex width="100%"> <CommandPaletteDemo /> </Flex> </Storybook.Demo>
import {addSuccessMessage} from 'sentry/actionCreators/indicator';
import {
CMDKAction,
CommandPaletteProvider,
} from 'sentry/components/commandPalette/ui/cmdk';
import {CommandPalette} from 'sentry/components/commandPalette/ui/commandPalette';
function YourComponent() {
return (
<CommandPaletteProvider>
<CMDKAction display={{label: 'Go to Flex story'}} to="/stories/layout/flex/" />
<CMDKAction
display={{label: 'Execute an action'}}
onAction={() => addSuccessMessage('Action executed')}
/>
<CMDKAction display={{label: 'Parent action'}}>
<CMDKAction
display={{label: 'Child action'}}
onAction={() => addSuccessMessage('Child action executed')}
/>
</CMDKAction>
<CMDKAction display={{label: 'Issues List'}}>
<CMDKAction
display={{label: 'Select all'}}
onAction={() => addSuccessMessage('Select all')}
/>
<CMDKAction
display={{label: 'Deselect all'}}
onAction={() => addSuccessMessage('Deselect all')}
/>
</CMDKAction>
<CommandPalette />
</CommandPaletteProvider>
);
}
CMDKAction accepts a resource prop — a function that takes the current search query and returns a TanStack Query options object. The children prop becomes a render function that receives the fetched results:
import type {CommandPaletteAsyncResult} from 'sentry/components/commandPalette/types';
<CMDKAction
display={{label: 'Projects'}}
resource={query => ({
queryKey: ['/projects/', {query}],
queryFn: () => fetchProjects(query),
// transform response into CommandPaletteAsyncResult[]
select: (data): CommandPaletteAsyncResult[] =>
data.map(p => ({
display: {label: p.name},
to: `/projects/${p.slug}/`,
})),
})}
>
{(results: CommandPaletteAsyncResult[]) =>
results.map(r => (
<CMDKAction key={'label' in r.display ? r.display.label : ''} {...r} />
))
}
</CMDKAction>;