Shortcut sheet
FreeEvery keyboard shortcut in one place: while it is open, pressing a shortcut lights its row instead of running it, and a filter narrows the list.
pnpm dlx shadcn@latest add https://caliperui.site/r/shortcut-sheet.jsonWhen to use #
Use it for
- Apps with more than a handful of shortcuts.
- Behind a ? key or a Help menu.
Skip it when
- Teaching one shortcut; show it beside its button.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/shortcut-sheet.json
Adds its 7 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
example.tsx
import { useState } from "react" import { Button } from "@/components/ui/button" import { ShortcutSheet } from "@/components/ui/shortcut-sheet" export function ShortcutSheetDemo() { const [open, setOpen] = useState(false); return ( <> <Button variant="secondary" onClick={() => setOpen(true)}>Keyboard shortcuts</Button> <ShortcutSheet open={open} onOpenChange={setOpen} groups={[ { title: "Go to", items: [{ keys: "G+I", label: "Inbox" }, { keys: "G+P", label: "Pipeline" }, { keys: "Mod+K", label: "Search everything" }] }, { title: "Records", items: [{ keys: "C", label: "New record" }, { keys: "E", label: "Edit the open record" }, { keys: "Mod+Enter", label: "Save" }, { keys: "Shift+D", label: "Duplicate" }] }, { title: "View", items: [{ keys: "Mod+\\", label: "Toggle the sidebar" }, { keys: "Shift+?", label: "Show this list" }] }, ]} /> </> ); }
API reference #
ShortcutSheet
component
PropTypeDefault
open *boolean—
onOpenChange *(open: boolean) => void—
groups *readonly ShortcutGroup[]—
titlestring"Keyboard shortcuts"
classNamestring—
Accessibility #
It exposes status semantics, with aria-label kept in step with state. Changes that matter are announced through a live region.
KeyBehaviour
EscapeCloses or cancels, then returns focus to where it came from.
EnterActivates the focused control.
Motion #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.