Data Display

Keycap Shortcut

A React component for keycap-styled shortcut labels — combine multiple keys, mod shows ⌘ or Ctrl per platform, and with listening enabled each keycap presses down and springs back when the user actually hits the matching key, with a ring flash once the whole combo is held.

Draws shortcut hints as physical keycaps. Pass a keys array to combine several keys (for example ['mod', 'K']); mod shows ⌘ on mac and Ctrl everywhere else. Turn on listen and, when the user actually presses the matching key, that keycap sinks and springs back on release, and the outer frame flashes a ring once the whole combo is held. The component only observes key presses and never intercepts them, so the page's own shortcuts keep working.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add keycap-shortcut.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

80
Active edited usageDefault props
<KeycapShortcut/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/keycap-shortcut.en.json

Or, once registries are configured in components.json, install it as @webberui/keycap-shortcut.

Usage

import { KeycapShortcut } from "@/components/ui/keycap-shortcut";

// Combo: shows ⌘ K on mac, Ctrl K elsewhere
<KeycapShortcut keys={["mod", "K"]} listen />

// Single key, inline in text
<p>
  Press <KeycapShortcut>Esc</KeycapShortcut> to close
</p>

// With a separator and the larger size
<KeycapShortcut keys={["shift", "mod", "P"]} separator="+" size="md" />

Props

PropTypeDefaultDescription
childrenReact.ReactNode—Single key text (e.g. "Esc", "K"); use either this or keys, keys wins
keysstring[]—Key combo array, e.g. ['mod', 'K']; mod shows ⌘ or Ctrl depending on the platform
listenbooleanfalseListen for real key presses; when on, pressing the matching key sinks the keycap and springs it back
size"sm" | "md""sm"Keycap size (24px / 28px tall)
separatorReact.ReactNode—Separator between combo keys (e.g. "+"); none by default
platform"auto" | "mac" | "other""auto"Display platform; auto detects after mount, and the first SSR render always uses other
pressDurationnumber80Press-down duration (ms), also written to --wb-keycap-shortcut-duration
classNamestring—className merged into the outermost container

resolveKeycap(token, isMac) is also exported by name: it returns a ResolvedKeycap (display text, screen-reader name, aria-keyshortcuts key name, and match identifiers), so you can reuse the same key-name mapping in your own UI.

ResolvedKeycap

FieldTypeDefaultDescription
labelstring—Text or symbol shown on the keycap
srLabelstring—Full name read by screen readers for symbol keycaps; undefined for plain-text keycaps
ariastring—Key name used in aria-keyshortcuts (e.g. Meta, Control, ArrowUp)
matchstring[]—Identifiers matched while listening

How it works

  • Key-name mapping: mod → ⌘ / Ctrl, alt → ⌥ / Alt, shift → ⇧, enter → ↵, esc → Esc, tab → Tab, space → Space (the Chinese build shows 空白鍵, "space bar"), arrowup and friends → ↑ ↓ ← →, backspace → ⌫; any other key name is uppercased as-is.
  • Listeners are attached to window keydown / keyup only while listen is true. Matching uses e.key (case-insensitive), with e.code filling in letters and digits — holding ⌥ on mac turns e.key into a special symbol, and the right keycap still lights up. Each keycap decides on its own whether its key is held.
  • No preventDefault: the component observes and never intercepts, so browser and page shortcuts still fire.
  • On mac, other keys fire no keyup while ⌘ is held, so releasing ⌘ resets every pressed state; losing window focus (blur) resets them too.
  • keydown events during IME composition (isComposing or keyCode 229) are skipped.
  • Timing is exposed as CSS variables: --wb-keycap-shortcut-duration (written from pressDuration) and --wb-keycap-shortcut-ease (default cubic-bezier(0.23,1,0.32,1)), both overridable globally. Release uses a spring with stiffness 600 and damping 20.

Accessibility

  • The outer element carries aria-keyshortcuts (e.g. Meta+K or Control+K, per platform), so assistive tech can read the full shortcut
  • Each keycap is a semantic kbd element; symbol keycaps (⌘, ⇧, ↵, arrows, and so on) hide the symbol from assistive tech and read an sr-only full name instead (e.g. "Command", "Shift")
  • Listening only changes the visuals and never touches any aria attribute, so screen readers are not disturbed by the key animation
  • When the user's system has reduce motion turned on, pressing only changes the background color, with no movement or bounce