Kbd

Free

A native `<kbd>` wrapper for rendering keyboard shortcuts and hint keys, with three visual variants and two sizes so every shortcut hint in the kit shares one styled source instead of one-off utility classes.

</>sv-kbd kbdkeyboardshortcuthotkeyhint

Complexity tier: Primitive Presents a value: held to semantic markup and contrast, with its right-to-left and print gaps recorded and the right-to-left debt allowed only to shrink.

import { SvKbdComponent } from '@styloviz/kbd';

Demo & usage

Basic usage

Usage example — open the gallery for the full interactive demo.

An interactive demo for this component lives in the gallery.

Open live demo

More examples

A shortcut you can hear

⌘ is U+2318 PLACE OF INTEREST SIGN. A screen reader says "place of interest sign", or nothing at all — and the entire content of a shortcut hint is which keys to press, so a hint made of projected glyphs is documentation nobody can hear. It is unreadable to a sighted Windows or Linux user too, who has never been taught the symbol. Give the component the key and it draws the glyph, knows what it is called, and hides the symbol from assistive tech behind the word. Glyphs work as tokens do, because hosts already have ⌘ hard-coded everywhere and a fix that needs a rewrite first never gets adopted.

example.htmlAngular
<sv-kbd key="cmd" />      <!-- draws ⌘, announces "Command" -->
<sv-kbd key="⌘" />        <!-- the same, from the glyph you already had -->
<sv-kbd key="esc" />      <!-- draws Esc, announces "Escape" -->

A chord is one thing, and breaks like one

"Ctrl +" at the end of a line and "C" at the start of the next is not a shortcut, it is two. chord renders the whole thing as one non-breaking group — nested <kbd> is the HTML spec's own idiom for it — and announces it once, in order, rather than reading three symbols nobody named. A literal plus is written ++.

example.htmlAngular
<sv-kbd chord="cmd+shift+K" />   <!-- announces "Command Shift K" -->
<sv-kbd chord="ctrl+++" />      <!-- Control and the plus key -->

A shortcut combo, laid out yourself

example.htmlAngular
<span class="inline-flex items-center gap-1">
  <sv-kbd key="cmd" />
  <sv-kbd key="K" />
</span>

Variants

example.htmlAngular
<sv-kbd variant="solid">Esc</sv-kbd>
<sv-kbd variant="ghost">Tab</sv-kbd>
<sv-kbd variant="plain">↵</sv-kbd>

Larger size with an aria-label

example.htmlAngular
<sv-kbd size="md" ariaLabel="Enter">↵</sv-kbd>

When to use

  • Hinting a keyboard shortcut next to a command, menu item or search input.
  • Labelling a hotkey in a tooltip, palette footer, or empty-state hint.
  • Not for standalone body copy — `<kbd>` communicates "a key you press," not general emphasis.

Async states

None — this component has nothing to load, so it has no loading, empty or error state to drive.

Inputs

NameTypeDefaultDescription
keystring''The key, by name or by glyph — `cmd`, `shift`, `esc`, `⌘`, `K`. THE POINT OF THIS INPUT IS THE SPOKEN NAME. `⌘` is U+2318 PLACE OF INTEREST SIGN and a screen reader says "place of interest sign", or nothing at all; `⇧` is UPWARDS WHITE ARROW; `↵` is DOWNWARDS ARROW WITH CORNER LEFTWARDS. None of those is the name of a key, and the entire content of a shortcut hint is which keys to press — so a hint made of projected glyphs is documentation nobody can hear. Given the key, the component draws the glyph AND knows what it is called, so the symbol is hidden from assistive tech behind the word. Glyphs are accepted as well as tokens because hosts already have `⌘` hard-coded in a hundred templates, and a fix that requires rewriting all of them first is a fix that never gets adopted.
chordstring''A whole chord — `"cmd+shift+K"` — rendered as one unbreakable group. "Ctrl +" at the end of a line and "C" at the start of the next is not a shortcut, it is two. A literal `+` is written `++`.
variantKbdVariant'solid'Visual weight.
sizeKbdSize'sm'Chip size.
ariaLabelstring''Accessible label when the projected content is a symbol a screen reader won't say usefully on its own (e.g. `↵`, `⌘`) — announced instead of the glyph. Leave unset for plain text keys (`Esc`, `Tab`), which already read fine.
customClassstring''Extra classes appended after the resolved variant/size classes.

Customization & theming

  • Three variants: solid (bordered, filled), ghost (bordered, transparent) and plain (no chrome, inherits surrounding text color).
  • Two sizes: sm (default) and md.
  • `customClass` appends extra utility classes for one-off placement (e.g. margins) without a wrapper element.
  • `key` takes a token or a glyph — `cmd`, `shift`, `esc`, `⌘`, `K` — and supplies both what is drawn and what is said. `SV_KBD_KEYS`, `svKbdKey()`, `svKbdChord()` and `svKbdSpoken()` are exported for building the same mapping elsewhere.
  • `chord` takes a whole combo (`"cmd+shift+K"`) and renders it as one unbreakable group.
  • `alt` and `option` are separate entries on purpose: the same physical key, and not the same word. A macOS user reads ⌥ and hears "Option"; a Windows user reads Alt and hears "Alt".

Best practices

  • Do: Use `variant="plain"` when the surrounding element already supplies its own background/border, to avoid a double-boxed look.
  • Do: Prefer `chord` for a multi-key combo. It keeps the group from wrapping mid-shortcut and announces it once, in order — laying it out by hand gives you neither.
  • Do: Prefer `key` over projected content wherever the key has a name. The component cannot read what you project, so `ariaLabel` is the only thing it can offer for that case — which is the whole reason `key` exists.
  • Tip: Unknown tokens pass through and are announced as themselves, so `key="F12"` and `key="K"` need no configuration.
  • Don't: Don't use it to style ordinary inline code — that's what a `<code>` element / code-block component is for.

Accessibility

  • Renders a semantic native `<kbd>` element; a chord nests one `<kbd>` per key inside an outer one, which is the HTML spec's own idiom for a chord.
  • When the component drew the glyph — `key` or `chord` — the symbol is `aria-hidden` and the spoken name is given as visually-hidden text, so a screen reader says "Command Shift K" rather than reading three symbols nobody named. `ariaLabel` replaces that wording.
  • When the host projects content instead, the component cannot read it and `ariaLabel` becomes an attribute on the element — the only thing available for that case.
  • A chord never wraps mid-shortcut.
  • Purely presentational otherwise — carries no interactive role or focus state of its own.

Feedback on Kbd

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.