Prodular UI

Hotkeys

Keyboard shortcuts for desktop apps: one listener, scopes, guards for fields and open menus, conflict detection, remapping and a shortcuts sheet that can turn single-key shortcuts off (WCAG 2.1.4).

npx prodular-ui add hotkeys

Shortcuts and the reference sheet

Typing in the field never triggers single keys. Shift ? opens the sheet, where each shortcut can be changed and single keys turned off.

Press G (off), [ or Shift? outside the field.

    Anatomy

    <HotkeysProvider>  <App /></HotkeysProvider>
    useHotkey("mod+k", openPalette, { id: "palette", description: "Open command palette" })useHotkey("shift+?", () => setHelp(true), { id: "help", description: "Show keyboard shortcuts" })<ShortcutsDialog open={help} onOpenChange={setHelp} />

    Guidance

    Use it when

    • Apps people use all day, where the mouse slows them down.
    • Single keys (G, [, ?) only for frequent actions, and always with the sheet so they can be turned off.
    • useHotkeyScope for shortcuts that only make sense while a panel or editor has focus.

    Avoid

    • Reimplementing shortcuts with your own keydown listeners.
    • Overriding browser and screen reader keys: Cmd or Ctrl plus L, T, W, R, F, and Tab.
    • Shortcuts without a description; they cannot be found or changed.

    Rules for AI agents

    Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.

    • Mount HotkeysProvider once near the root and register shortcuts with useHotkey(keys, handler, { id, description, group }).
    • Write keys as "mod+k", "shift+?", "g" or "escape". mod is Cmd on macOS and Ctrl elsewhere.
    • Always render ShortcutsDialog and open it with shift+?. It is how people discover, remap and turn off shortcuts.
    • Show shortcuts in menus and tooltips with HotkeyKeys or useHotkeyKeys(id), so they reflect the person's remapping.
    • Do not set allowInInputs on single-key shortcuts.
    • Open CommandDialog from useHotkey("mod+k"), not from a separate listener.

    API

    HotkeysProvider

    PropTypeDefaultDescription
    storageKeystring | null"prodular-ui:hotkeys"Where remapping and the single-key switch are saved. null keeps them in memory.

    useHotkey

    PropTypeDefaultDescription
    keysstring"mod+k", "shift+?", "g", "[", "escape".
    options{ id, description, group, scope, enabled, allowInInputs, allowInOverlays, preventDefault }id and description make it appear and remappable in the sheet.

    useHotkeyScope

    PropTypeDefaultDescription
    (scope, active)(string, boolean) => voidTurns a scope on while active.

    ShortcutsDialog

    PropTypeDefaultDescription
    openbooleanControlled with onOpenChange.

    HotkeyKeys

    PropTypeDefaultDescription
    keysstringRenders the keys as Kbd, with the platform's symbols.

    Installation

    The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.

    npx prodular-ui add hotkeys# or, with the registry in components.jsonnpx shadcn@latest add @prodular/hotkeys