useShortcut React hook in TypeScript
v1.0.0Added in 1.0.0
A React keyboard shortcut hook in mod+k notation: bind shortcuts, match events and show them as ⌘K on a Mac or Ctrl+K elsewhere.
Press the shortcuts listed in the panel: the matching row lights up and the log says what ran. Type a combo into the playground (mod+k, shift+?, alt+n) to bind it live and see how it reads on Apple devices and everywhere else. Single keys like / stay quiet while you type in the search field; combos with a modifier still work there.
useShortcut is a free React hook in the React hooks and utilities category, written in TypeScript for React 19. It installs as source with npx wingo-ui@latest add use-shortcut, together with useMediaQuery.
Add to a project
Requirements: React 19, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add use-shortcutUsage
Import useShortcut from @/hooks/use-shortcut.
import { useRef } from "react"
import { useShortcut, useShortcutLabel } from "@/hooks/use-shortcut"
export function SearchField() {
const input = useRef<HTMLInputElement>(null)
const label = useShortcutLabel("/")
// a bare "/" is ignored while someone types in another field
useShortcut("/", () => input.current?.focus())
useShortcut("mod+k", () => input.current?.focus())
return (
<label className="flex items-center gap-2">
<input ref={input} placeholder="Search listings" aria-keyshortcuts={label.aria} />
<kbd>{label.text}</kbd>
</label>
)
}API
shortcut*default"mod+k"string | readonly string[] | null | undefined | falseuseShortcut(shortcut, handler, options?): the combo in mod+k notation ("shift+mod+p", "alt+n", "/", "escape"). mod is ⌘ on Apple devices and Ctrl elsewhere. Pass an array for alternatives; null, "" or false binds nothing, so a component can take a shortcut prop its caller clears.
handler*(event: KeyboardEvent) => voidRuns when the shortcut is pressed. It may change on every render; the listener is not re-added.
enableddefaulttruebooleanTurns the binding off without unmounting, for example while a panel is closed.
allowInInputsbooleanFire while focus is in a text field. By default only combos with ctrl, meta, mod or alt do, so a bare / or ? never steals a keystroke from someone typing.
preventDefaultdefaulttruebooleanCalls event.preventDefault() when the shortcut fires, so mod+s does not also open the browser's save dialog.
repeatdefaultfalsebooleanFire again while the key is held down.
capturedefaultfalsebooleanListen in the capture phase, before handlers inside the page.
Parts
useShortcutLabel
hookThe display form for the current device: keys ["⇧", "⌘", "P"] for separate key caps, text "⇧⌘P" (Ctrl+Shift+P elsewhere) for menus, aria for aria-keyshortcuts. Renders the non-Apple form on the server, then swaps. Signature: (shortcut: string | null | undefined) => { keys: string[]; text: string; aria: string | undefined }.
formatShortcut
functionThe same labels outside React, for a given platform. Signature: (shortcut: string, apple: boolean) => string[].
formatShortcutText
functionThe same labels outside React, for a given platform. Signature: string.
matchesShortcut
functionTrue when a keyboard event (DOM or React) is exactly this combo. Falls back to the physical key when the layout types a non-Latin character, so mod+k also works on a Romanian or Cyrillic layout and with Option held on a Mac. Signature: (event: ShortcutEvent, shortcut: string | ParsedShortcut, apple?: boolean) => boolean.
parseShortcut
functionThe parsed combo (cached), the value for aria-keyshortcuts, and whether focus sits in an input, textarea, select or contenteditable element. Signature: (shortcut: string) => ParsedShortcut | null.
ariaKeyShortcuts
functionThe parsed combo (cached), the value for aria-keyshortcuts, and whether focus sits in an input, textarea, select or contenteditable element. Signature: (shortcut, apple) => string | undefined.
isTypingTarget
functionThe parsed combo (cached), the value for aria-keyshortcuts, and whether focus sits in an input, textarea, select or contenteditable element. Signature: (target) => boolean.
UseShortcutOptions
typeThe options object: enabled, allowInInputs, preventDefault, repeat and capture.
ShortcutLabel
typeWhat useShortcutLabel returns: { keys: string[]; text: string; aria: string | undefined }.
ParsedShortcut
typeWhat parseShortcut returns: the key plus mod, ctrl, meta, alt and shift flags.
ShortcutEvent
typeThe keyboard event fields matchesShortcut reads: key, code and the modifier flags.
Examples
Keyboard list navigation
j / k or the arrows move through an inbox and Enter opens it, bound only while the list has focus.
Send with ⌘ Enter
A modified combo fires inside the textarea, so the comment sends without leaving the keyboard.
Dependencies
Files
- hooks/use-shortcut.ts
FAQ
Is the useShortcut hook free?
Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.
How do I install useShortcut?
Run npx wingo-ui@latest add use-shortcut. It also adds the Wingo UI item it builds on (useMediaQuery). With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/use-shortcut.json.
See also
Used in
More React hooks and utilities
Articles using this component
- React Command Palette: Cmd+K, Nested Pages and Mobile
Component guides9 min read