busy-office-ui
Menu

Keyboard key

A keycap chip for the native <kbd> element — shortcut hints in captions, help dialogs, empty states. Em-sized, so it follows the text it sits in; case is preserved (j is not J). Not for an on-screen control's label — <kbd> means a key the user presses on their keyboard. Referring to a button in the UI is just its name in text, and if you want it to look like the control, that is a button.

Inline — a hint in running text

Press / to filter, or Shift + Enter to approve without opening.

View code
<p>Press <kbd class="bo-kbd">/</kbd> to filter, or
<kbd class="bo-kbd">Shift</kbd> + <kbd class="bo-kbd">Enter</kbd> to
approve without opening.</p>

The weighted bottom edge is what makes it read as a key. Combos are separate chips joined by a plain + — one chip per physical key.

A shortcut list — composed with Key-value facts

/
Focus the filter
Enter
Open the selected row
Shift + Enter
Approve without opening
Esc
Back to the cell
View code
<dl class="bo-kv bo-kv--rows">
  <div><dt><kbd class="bo-kbd">/</kbd></dt><dd>Focus the filter</dd></div>
  <div><dt><kbd class="bo-kbd">Enter</kbd></dt><dd>Open the selected row</dd></div>
  <div><dt><kbd class="bo-kbd">Shift</kbd> + <kbd class="bo-kbd">Enter</kbd></dt><dd>Approve without opening</dd></div>
  <div><dt><kbd class="bo-kbd">Esc</kbd></dt><dd>Back to the cell</dd></div>
</dl>

.bo-kv --rows aligns keys and descriptions; the chip resets the label uppercase so Esc stays Esc. The full overlay version is the Keyboard map.

Markup

<!-- Always on the native <kbd> element — the semantics come free;
     the class only paints the keycap. Combos are separate chips joined
     by plain "+" text. -->
<kbd class="bo-kbd">Shift</kbd> + <kbd class="bo-kbd">Enter</kbd>

Quick reference generated

ClassRole
.bo-kbd block (root)

API generated from CSS

Blocks bo-kbd
JS required None — CSS-only.
  • Use the native <kbd> element, not a span — screen readers and reader modes already know what it means; the class only paints.
  • One chip per physical key; join combos with plain text (+, then) so AT reads the sequence naturally.
  • Case is meaningful and preserved — the chip resets any inherited text-transform (a grid label context uppercases otherwise).
  • Forced colors: the border is the boundary and borders survive — no special-casing needed.
  • Show the keys your app actually binds — the framework documents its own behavior keys on JS behaviors (generated from the same source the behaviors use).
Contrast — 12 AA pairs this component uses (generated, CI-gated)
TextonLightDark
text-secondary bg-surface 10.31 11.46
text-secondary bg-muted 9.37 9.75
text-muted bg-muted 6.87 5.66
text-secondary bg-selected 9.88 8.41
text-secondary bg-canvas 9.86 12.82
border-control bg-muted 4.39 5.66
accent bg-muted 4.97 7.72
warning-strong bg-muted 4.56 6.69
danger bg-muted 4.39 5.19
text-primary bg-muted 16.12 13.75
success-text bg-muted 4.56 10.23
danger-text bg-muted 5.88 7.57

Maturity generated

Introduced
v0.3.0
CSS floor
Chrome/Edge 99 · Firefox 97 · Safari 15.4
Alignment scored
2026-08-21
Assistive-tech evidence
None recorded

Pin this component's first release with npm i @busy-office/ui@0.3.0. The floor is derived from this component's stylesheet alone — set by @layer — so it sits at or below the whole framework's Chrome/Edge 119 · Firefox 129 · Safari 17.5. No assistive-technology runtime result is recorded for any component: it needs a human listening to VoiceOver and NVDA on owner hardware; no gate in this repo can simulate announcement behaviour. What automation covers instead is test:axe across every page at 1440 and 390, and check:forced-colors — see accessibility.

Design-system alignment generated

100% (15/15) — how closely this component follows the design language. Each rule is scored 0-3 against a checkable citation; rules that don't apply leave the denominator. Scored 2026-08-21.

Rule Score Evidence
Typography 3 / 3 inline mono now consumes --bo-font-size-mono-inline, the one ratio in the scale — a fraction of the host, which no absolute step can express (94.13)
Colour 3 / 3 zero raw colour; border/background/text all tokens
Spacing 3 / 3 min-inline-size, padding and the weighted bottom edge all carry their reason — the edge comment names what it buys ("reads as a KEYCAP")
Interaction n/a paints the native <kbd>; ships no behavior
Content 3 / 3 the opener carries the required wrong-choice clause and links the alternative (94.10)
Fit 3 / 3 shortcut hints in captions, help dialogs and empty states; one chip per physical key
↑↓ move Enter open Esc close