CommandPalette
A keyboard-first command launcher (Cmd/Ctrl-K) for searching and running actions across the app.
Powered by cmdk; the dialog-hosted CommandMenu uses role="dialog" with an sr-only title; ArrowUp / ArrowDown navigate items; Enter runs the focused item; Esc closes.
Preview
tsx
import {
Button,
CommandEmpty,
CommandFooter,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandMenu,
CommandSeparator,
} from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open command palette</Button>
<CommandMenu open={open} onOpenChange={setOpen}>
<CommandInput />
<CommandList>
<CommandEmpty />
<CommandGroup heading="Suggestions">
<CommandItem onSelect={() => setOpen(false)}>New file</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>Open file</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>Save</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="System">
<CommandItem onSelect={() => setOpen(false)}>Settings</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>Sign out</CommandItem>
</CommandGroup>
</CommandList>
<CommandFooter />
</CommandMenu>
</>
);
}
CommandPalette is the raw cmdk surface. For the common case — a dialog that opens on Cmd/Ctrl-K — drop in the pre-wired CommandMenu.
import { Button, CommandEmpty, CommandFooter, CommandGroup, CommandInput, CommandItem, CommandList, CommandMenu, CommandSeparator,} from "@arshad-shah/cynosure-react";import { useState } from "react";
function App() { const [open, setOpen] = useState(false); return ( <> <Button onClick={() => setOpen(true)}>Open palette</Button> <CommandMenu open={open} onOpenChange={setOpen}> <CommandInput /> <CommandList> <CommandEmpty /> <CommandGroup heading="Actions"> <CommandItem onSelect={() => setOpen(false)}>Save</CommandItem> <CommandItem onSelect={() => setOpen(false)}>Settings</CommandItem> </CommandGroup> </CommandList> <CommandFooter /> </CommandMenu> </> );}Variants
Section titled “Variants”Grouped with shortcuts
Section titled “Grouped with shortcuts”Use CommandGroup heading="…" to label sections and shortcut="⌘K" on items to render Kbd chips on the right.
Preview
tsx
import {
Button,
CommandEmpty,
CommandFooter,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandMenu,
CommandSeparator,
} from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open palette</Button>
<CommandMenu open={open} onOpenChange={setOpen}>
<CommandInput />
<CommandList>
<CommandEmpty />
<CommandGroup heading="File">
<CommandItem shortcut="⌘N" onSelect={() => setOpen(false)}>
New file
</CommandItem>
<CommandItem shortcut="⌘O" onSelect={() => setOpen(false)}>
Open file
</CommandItem>
<CommandItem shortcut="⌘S" onSelect={() => setOpen(false)}>
Save
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Edit">
<CommandItem shortcut="⌘Z" onSelect={() => setOpen(false)}>
Undo
</CommandItem>
<CommandItem shortcut="⇧⌘Z" onSelect={() => setOpen(false)}>
Redo
</CommandItem>
</CommandGroup>
</CommandList>
<CommandFooter />
</CommandMenu>
</>
);
}
With icons and descriptions
Section titled “With icons and descriptions”CommandItem accepts an icon slot and a description line shown under the label.
Preview
tsx
import {
Button,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandMenu,
} from '@arshad-shah/cynosure-react';
import { useState } from 'react';
function DocIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path
d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z"
stroke="currentColor"
strokeWidth="2"
strokeLinejoin="round"
/>
<path d="M14 3v5h5" stroke="currentColor" strokeWidth="2" strokeLinejoin="round" />
</svg>
);
}
function GearIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="2" />
<path
d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 0 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9c.4.6 1 .9 1.5 1H21a2 2 0 0 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"
stroke="currentColor"
strokeWidth="2"
/>
</svg>
);
}
export default function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open palette</Button>
<CommandMenu open={open} onOpenChange={setOpen}>
<CommandInput />
<CommandList>
<CommandEmpty />
<CommandGroup heading="Navigation">
<CommandItem
icon={<DocIcon />}
description="Browse documents in this workspace"
onSelect={() => setOpen(false)}
>
Open file
</CommandItem>
<CommandItem
icon={<GearIcon />}
description="Workspace preferences"
shortcut="⌘ ,"
onSelect={() => setOpen(false)}
>
Settings
</CommandItem>
</CommandGroup>
</CommandList>
</CommandMenu>
</>
);
}
Cmd/Ctrl-K shortcut
Section titled “Cmd/Ctrl-K shortcut”CommandMenu registers a global Cmd/Ctrl-K listener while mounted. Press the keys to toggle.
Preview
tsx
import {
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandMenu,
Kbd,
} from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [open, setOpen] = useState(false);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<p style={{ fontSize: '0.875rem', margin: 0 }}>
Press <Kbd>⌘</Kbd>
<Kbd>K</Kbd> (or <Kbd>Ctrl</Kbd>
<Kbd>K</Kbd>) to toggle the palette.
</p>
<CommandMenu open={open} onOpenChange={setOpen}>
<CommandInput />
<CommandList>
<CommandEmpty />
<CommandGroup heading="Quick actions">
<CommandItem onSelect={() => setOpen(false)}>New document</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>Invite teammate</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>Toggle theme</CommandItem>
</CommandGroup>
</CommandList>
</CommandMenu>
</div>
);
}
PropTypeDefaultDescription
children
ReactNode
No results found.
Pass a string like `"⌘K"` or `"Ctrl+Shift+P"` — split on `+` / whitespace
and rendered as a series of `<Kbd>` chips. JSX children are rendered
untouched.
Accessibility
Section titled “Accessibility”- The dialog-hosted
CommandMenurenders a screen-reader-onlyDialogTitlefor an accessible name. - ArrowUp / ArrowDown move focus through visible items;
Home/Endjump to the first / last. Enteractivates the focused item via itsonSelecthandler;Esccloses the dialog and returns focus to the trigger.CommandInputis the only focusable text input — typing filters items by label andkeywords.- The
CommandFooterhints (↵ select,Esc close) are decorative; they do not steal keyboard focus.
Recipes
Section titled “Recipes”- Pass
keywords={["new", "create"]}onCommandItemto widen what the filter matches without changing the label. - Use
shouldFilter={false}onCommandMenuwhen you fetch results asynchronously, and render<CommandLoading />while pending. - Group destructive items at the bottom under a separate
CommandGroup heading="Danger"so they are never the first match. - Pair with
Kbdin your own onboarding copy (“Press ⌘K to search”) so the affordance is discoverable.