Features
- Searchable Command Dialog: Command palette with fuzzy search and real-time filtering.
- Groupable Command List: Organize commands into logical groups with optional headings.
- Selectable Items: Items support click actions, selection states, and checkmark indicators.
- Keyboard Navigation: Full keyboard support with arrow keys, Enter, and Escape navigation.
- Custom Shortcuts: Optional shortcut labels shown beside each command item.
- Empty State Handling: Automatically displays a fallback when no items match the query.
- Loopable Navigation: Optional looping behavior for continuous up/down key cycling.
- Custom Filtering Logic: Swap out the built-in filter with your own function.
- Accessible & Composable: ARIA roles and headless architecture for complete flexibility.
- Responsive Design: Adapts gracefully to different screen sizes and containers.
- Dialog or Inline Support: Can be used as a floating dialog or embedded inline.
About
This component uses the @gentleduck/vim library under the hood.
Installation
npx @gentleduck/cli add command
npx @gentleduck/cli add command
Usage
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
TooltipProvider,
} from '@/components/ui'import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
TooltipProvider,
} from '@/components/ui'<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Search GitHub</CommandItem>
<CommandItem>Search Twitter</CommandItem>
<CommandItem>Search Discord</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>General</CommandItem>
<CommandItem>Profile</CommandItem>
<CommandItem>Notifications</CommandItem>
</CommandGroup>
</CommandList>
</Command><Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Search GitHub</CommandItem>
<CommandItem>Search Twitter</CommandItem>
<CommandItem>Search Discord</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>General</CommandItem>
<CommandItem>Profile</CommandItem>
<CommandItem>Notifications</CommandItem>
</CommandGroup>
</CommandList>
</Command>Examples
Dialog
Press ⌘J
To show the command menu in a dialog, use the <CommandDialog /> component, or use the <Button/> component with the command variant.
import { useKeyCommands } from '@gentleduck/vim/react'
export function CommandMenu() {
const [open, setOpen] = React.useState(false)
useKeyCommands({
'ctrl+j': {
name: '⌘j',
description: 'Open command menu',
execute: () => {
window.event?.preventDefault()
setOpen(true)
},
},
})
return (
<CommandDialog
open={open}
onOpenChange={setOpen}
>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Settings</CommandItem>
<CommandItem>Messages</CommandItem>
<CommandItem>Search</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
)
}import { useKeyCommands } from '@gentleduck/vim/react'
export function CommandMenu() {
const [open, setOpen] = React.useState(false)
useKeyCommands({
'ctrl+j': {
name: '⌘j',
description: 'Open command menu',
execute: () => {
window.event?.preventDefault()
setOpen(true)
},
},
})
return (
<CommandDialog
open={open}
onOpenChange={setOpen}
>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Settings</CommandItem>
<CommandItem>Messages</CommandItem>
<CommandItem>Search</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
)
}API Reference
Command Props
props(React.HTMLProps<HTMLDivElement>): All native div props are supported.
CommandInput Props
placeholder(string, optional): Placeholder text in the input. Default is'Search...'.autoFocus(boolean, optional): Automatically focus input on mount. Default istrue.onChange(React.ChangeEventHandler, optional): Triggered when the input value changes....props(React.HTMLProps<HTMLInputElement>): All native input props are supported.
CommandList Props
props(React.HTMLAttributes<HTMLUListElement>): All nativeulprops are supported.
CommandItem Props
value(string, optional): The internal value for selection.onSelect((value: string) => void, optional): Called when the item is selected.onClick(React.MouseEventHandler, optional): Native click event.onKeyDown(React.KeyboardEventHandler, optional): Native keydown event....props(React.HTMLProps<HTMLLIElement>): All nativeliprops are supported.
CommandGroup Props
heading(string, optional): Optional heading for the group.props(React.HTMLProps<HTMLDivElement>): All nativedivprops are supported.
CommandEmpty Props
props(React.HTMLAttributes<HTMLHeadingElement>): All nativeh6props are supported.
CommandShortcut Props
keys(string, optional): Keyboard shortcut string (e.g."ctrl+K").onKeysPressed(() => void, optional): Triggered when shortcut is pressed.variant('default' | 'secondary', optional): Visual style variant....props(React.HTMLProps<HTMLElement>): All nativekbdprops are supported.
CommandSeparator Props
props(React.HTMLProps<HTMLDivElement>): All nativedivprops are supported.
CommandDialog Props
props(DialogProps): All props supported by the underlying<Dialog />component.
Types
CommandContextType
search(string): Current search query value.setSearch(React.Dispatch<React.SetStateAction<string>>): Setter for search query.
CommandRefsContextType
commandRef(React.RefObject<HTMLDivElement | null>): Root command container reference.listRef(React.RefObject<HTMLUListElement | null>): UL element holding items.emptyRef(React.RefObject<HTMLHeadingElement | null>): Empty state heading ref.inputRef(React.RefObject<HTMLInputElement | null>): Search input field reference.selectedItem(HTMLLIElement \| null): Currently selected item.setSelectedItem(React.Dispatch<React.SetStateAction<HTMLLIElement | null>>): Setter for selected item.items(React.RefObject<HTMLLIElement[]>): All command items.filteredItems(React.RefObject<HTMLLIElement[]>): Filtered items after search.groups(React.RefObject<HTMLDivElement[]>): Groups of command items.
CommandBadgeProps (CommandShortcut)
keys(string, optional): Keyboard shortcut string (e.g.'ctrl+K').onKeysPressed(() => void, optional): Called when the shortcut is triggered.variant('default' | 'secondary', optional): Visual style....props(React.HTMLProps<HTMLElement>): Nativekbdelement props.