shadcn.io is not affiliated with official shadcn/ui
Keyboard Shortcuts Dialog Block for React
A markdown notes app with its keyboard shortcuts sheet shown open: 16 shortcuts in three columns drawn as keycaps, a Mac and Windows switch that rewrites the caps, a search, and a key tester that names any chord you press.
Installation
Overview
Show people every shortcut in one place, with this keyboard shortcuts dialog for React with Base UI. It opens from the Notes page of Chordnote, a markdown notes app: the header holds an outline Button with a Kbd hint for the question mark key, and the notes list and editor are drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The dialog groups 16 shortcuts into Navigation, Editing and View, three columns from the dialog's wider sizes, each drawn as keycaps. A Toggle Group switches between Mac and Windows and Linux and rewrites the caps, so Command becomes Control and Option becomes Alt; a search Input filters by name. At the foot a key tester names whatever you press and lights the matching row. Done is the only Shine Button. For preview the dialog is drawn open in place when the page loads; the header button, or the question mark key anywhere in the block while no field has focus, opens the real Dialog. For editors, boards, docs and any app with a shortcut map.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the sheet is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The header's Shortcuts button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same SheetFields component and share the block's state, so what you set in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How does the key tester work, and does it run anything?
Focus the Press a shortcut button and press a chord. The block reads the modifiers and the key from the event, matches the chord against the 16 shortcuts on the platform you chose, lights the row and says it in words: "Command K: Search notes. Nothing ran." An unknown chord says "No shortcut for Control J". Nothing runs: the tester only checks the keys and stops the browser's own response while it has focus, so Control P does not print. Tab, Enter, Space and Escape still work as they do anywhere, so the button never traps you. It is hidden on phones, which have no keyboard to press.
How are the keys rewritten for Mac and Windows?
Each shortcut is typed once with names for the modifiers (mod, alt, shift) and then the key. The Toggle Group picks a platform, and one table prints mod as the Command symbol or Ctrl, alt as the Option symbol or Alt. A screen reader gets the spoken name instead of the symbol: "Command K", "Control K". The page starts on Mac keys and switches to Windows and Linux after mount when the browser does not report a Mac.
Does the question mark key really open it?
Yes, from anywhere inside the block while no text field has focus. The listener sits on the block's own element, never on the window, so it does not take the key from the rest of the page, and it ignores the key with Command or Control held. In your app attach it to your app shell, keep the same field check, and list the key beside the button with aria-keyshortcuts.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus is trapped while it is open, and Escape, Done and the close button return focus to the Shortcuts button. The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it and its close button close it and put focus back on the Shortcuts button. Each row reads as a list item with its name first and the chord after it.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet with Done pinned at the bottom. The three groups stack into one column that scrolls above it, and the key tester is hidden. The real dialog keeps the Dialog's own phone layout: a sheet stuck to the bottom of the screen.
Related
- Pro
Keyboard Shortcuts Navbar
App toolbarsAn app navbar whose shortcuts work: G then H, P or S moves between pages, a question mark opens a dialog with every key in a table, and each link shows its keys on hover and keyboard focus.
- Pro
Command Palette Dialog
Pickers and searchA docs workspace's command palette shown open over its page: Recent and Pages when the field is empty, and a typed greater-than, at or hash turns it to Actions, People or Pages, each with its own groups and count, and each choice edits the drawn page.
- Pro
Search Replace Dialog
Drawers and popoversA document editor's find bar shown open over real text: every match marked with an underline, the current one ringed and scrolled into view, a count like 3 of 12, case and whole-word toggles, Replace and Replace all.
- Pro
An invoicing app's quick-actions dialog shown open: eight action tiles in two columns, a star on each that pins it into one of four slots at the top, arrow keys across the tiles and a letter that runs an action.
- 333Pro
Global Search Command Menu
Search everythingA company intranet's command menu shown open: one input searches pages, docs, people and tags at once, each type is a group of three matches with a row that opens it in place, and the foot counts the results by type.
- Pro
A time tracker's Today page with a preferences sheet shown open where each setting shows its effect: a theme choice over a preview card, a text size and a reduce-motion switch acting on a sample, a default view and two behaviour switches.