Keycap Gallery · one way to show a key, everywhere

Six ways to draw a keyboard key, from most understated to most emphatic. Every one rides the same base cap and the same glyph rules — the skin is the only variable. Toggle font and theme above; the native twin lives in KeycapGalleryView.swift.

§1The problem

Telling a user “press Option-Command-L” in prose is slow to parse and easy to get wrong across platforms. A keycap — the little rounded box around — turns an instruction into something the eye recognises instantly as “a key you press.” We need this in four places that don’t share a rendering engine:

SPA (React) — help modal, tooltips
?
Public web docs — manual on bristlenose.app
S
CLI — terminal help output
⌘F
Native macOS — custom UI & teaching
E

Two rules are already settled and non-negotiable (Apple Style Guide + Gruber, see design-keyboard-shortcuts.md): modifier order is Fn → Control → Option → Shift → Command, and glyphs concatenate with no separator (⇧⌘S) while spelled-out words take a + (Ctrl+Shift+S). This gallery is about the skin, not those rules.

§2The glyphs — nailed down

The one source of truth for every surface. The Unicode glyph is the cross-platform constant; the SF Symbol is the native upgrade (weight/scale control, optical alignment) with the Unicode glyph as its guaranteed fallback.

KeyGlyphUnicodeSF SymbolNon-Mac word
Command U+2318command
Option / Alt U+2325option Alt
Shift U+21E7shift Shift
Control U+2303control Ctrl
Caps Lock U+21EAcapslock Caps Lock
Return U+21A9return Enter
Enter (numpad)U+2324return Enter
Escape U+238Bescape Esc
Delete (back) U+232Bdelete.left Backspace
Forward deleteU+2326delete.right Delete
Tab U+21E5arrow.right.to.lineTab
Space U+2423space Space
Arrows ↑↓←→U+2191…arrow.up … ↑↓←→
Fn / Globe 🌐U+1F310globe Fn

Font gotcha: render the modifier glyphs in --bn-font-mono (SF Mono) or the system font — never Inter. Inter’s coverage of ⌘⌥⇧⌃ is incomplete, so the body font silently falls back per-glyph to a different face, and your caps end up mismatched. Every cap in this gallery uses the mono stack for the glyph.

§3The six skins

AFlat

Subtle fill, hairline border, no shadow. The quietest cap. Best for dense inline use where a raised key would be too loud — table cells, filter chips, sidebar hints.

joinedS single? s non-MacCtrl+S
CSS
.cap { display:inline-flex; align-items:center; justify-content:center;
  min-width:1.7em; height:1.7em; padding:0 .42em;
  font-family:var(--bn-font-mono); font-size:var(--bn-text-label); font-weight:500;
  color:var(--bn-colour-text); border-radius:5px; }
.cap--flat { background:var(--bn-colour-badge-bg); border:1px solid var(--bn-colour-border); }
BRaisedRecommended · help & teaching

A physical key: soft top-to-bottom gradient face, a darker bottom edge, and an inner top highlight. Reads as tactile without shouting. The right choice when the key is the content — the help modal, onboarding, “press this” moments.

joinedS splitL single?
CSS
.cap--raised {
  background:linear-gradient(var(--cap-face), var(--cap-face-lo));
  border:1px solid var(--bn-colour-border-hover);
  box-shadow:0 1.5px 0 0 var(--cap-edge),          /* bottom edge  */
             inset 0 1px 0 0 var(--cap-highlight); /* top highlight */
}
/* --cap-face / --cap-face-lo / --cap-highlight / --cap-edge:
   add as light-dark() tokens; face is a hair lighter than badge-bg
   so the top edge catches light. */
COutline

Transparent face, border only. Vanishes into tinted panels (the inspector, a coloured callout) where a filled cap would fight the background. Also the lightest option that still reads as “a key.”

on a tinted panel K / Shift+Tab
CSS
.cap--outline { background:transparent; border:1px solid var(--bn-colour-border-hover); }
DSolid (inverted chip)

Dark pill on light (and light on dark). Highest emphasis — a single hero shortcut in an empty state or command-palette prompt (“press K”). Use sparingly; one per screen.

joinedK single/
CSS
.cap--solid { background:var(--chip-bg); color:var(--chip-text);
  border:1px solid transparent; font-weight:600; }
/* --chip-bg: light-dark(#1a1a1a, #e5e7eb); --chip-text: light-dark(#f4f4f5, #1a1a1a) */
EMono gridRecommended · dense lists

iA Writer’s trick: uniform ch-width caps in a monospace face, so single characters form true columns. When ten shortcuts stack in a help list, the letters line up as a scannable vertical index. This is Phase 4 of the shortcuts doc.

j
Next quote
k
Previous quote
s
Star
K
Extend selection up
.
Toggle both sidebars
Close / clear
CSS
.cap--grid { background:var(--bn-colour-badge-bg); border:1px solid var(--bn-colour-border);
  font-family:var(--bn-font-mono); min-width:2.2ch; padding:0 .3em; }
/* right-align the .keys column; monospace makes every single char the same width */
FBare glyph

No cap at all — just the glyph in muted/secondary colour. This is the native inline-shortcut idiom: menu items and list rows show ⌘S right-aligned in grey, no box (macOS draws it this way everywhere). Also the CLI’s only option, since terminals can’t box-draw a cap cleanly.

Export Report…⇧⌘E
Find…⌘F
Settings…⌘,
CSS
.cap--bare { background:transparent; border:0; padding:0; min-width:0;
  color:var(--bn-colour-muted); font-family:var(--bn-font-mono); }
/* native menus/rows: NEVER draw a cap — the OS shows bare grey glyphs, right-aligned */

§4Joined vs split

An orthogonal choice you make per surface, independent of skin: do modifiers fuse into the letter, or does each key get its own cap?

S
Joined — menu-bar truth, compact.
Default for glyphs. Reads as one gesture.
S
Split — teachable, each key discrete.
Better for onboarding & non-Mac words.

Rule of thumb: joined for compact reference (menus, tooltips, dense lists — matches how macOS itself renders shortcuts); split when teaching a combo for the first time, and always for spelled-out non-Mac words (Ctrl + S) where fusing would be unreadable.

§5In context

Inline in prose (docs & tooltips)

To save the current view, press S. Star a quote with s, or select several and press t to tag them all at once. Press ? any time to see every shortcut.

Flat (A) at ~0.78rem sits on the text baseline without disturbing line-height. This is what the public docs and tooltips should use.

The help modal (what ships today, refined)

j
Next quote
J
Extend selection down
s
Star quote
.
Toggle both sidebars

Today’s help-overlay.css is essentially skin B with a flat-bottom shadow. The refinement: gradient face + inner highlight so it reads as a real key in both themes, plus the mono glyph-safe font.


Recommendation. Ship B · Raised as the default keycap (help, teaching, docs headers), A · Flat for inline prose & tooltips, E · Mono grid for the aligned help list, and F · Bare for native menus and the CLI. C and D are situational (tinted panels; hero prompts). All six are one CSS file and one SwiftUI file, driven by the same glyph map in §2. Decisions frozen in docs/design-keycaps.md.