Gesso
Actions

Kbd

Keyboard shortcut chip for Command items and Tooltips.

Kbd shows a key or a shortcut the reader can press, as a small chip beside a label, at the end of a Command row, or inside a Tooltip. Kbd is one key and KbdGroup sets several in a row as one shortcut, and inside a Tooltip the chip inverts to match it.

esc⌘K⇧⌘P↑↓

Usage

import { Kbd, KbdGroup } from '@/components/ui/kbd';

<KbdGroup>
  <Kbd>⌘</Kbd>
  <Kbd>K</Kbd>
</KbdGroup>

Both take every <kbd> attribute, and className merges onto the chip.

Keys and shortcuts

A key is 20px tall and at least 20px wide, so a single letter sits in a square and a word like esc or Shift widens it. It is set at text-xs in the sans face rather than the browser's monospace, in text-fg-muted on bg-surface-sunken. An icon inside a key is drawn at 12px unless it has its own size-* class, so an icon from Phosphor fits without sizing it. KbdGroup sets its keys 4px apart, for keys pressed together. Kbd shows the key and does not listen for it, so wire the shortcut up yourself.

In a command row

Wrap the key in CommandShortcut, which pushes it to the end of the row.

import { Plus } from '@phosphor-icons/react';
import { CommandItem, CommandShortcut } from '@/components/ui/command';
import { Kbd } from '@/components/ui/kbd';

<CommandItem onSelect={createIssue}>
  <Plus />
  Create issue
  <CommandShortcut>
    <Kbd>C</Kbd>
  </CommandShortcut>
</CommandItem>

Inside a tooltip

Tooltip is an inverted chip, bg-fg with text-background, and a key inside its content inverts with it, to text-background on a 16% wash of the background. The switch keys off the kit Tooltip's data-slot="tooltip-content", so it needs no prop, and on any other surface the key keeps its sunken fill. Hover the button to see it.

Accessibility

  • Kbd renders a <kbd>, and KbdGroup renders a <kbd> around its keys, which HTML reads as one input made of several keys.
  • <kbd> has no ARIA role, so a screen reader reads the key as plain text, and a symbol like ⌘ is spoken however that screen reader names the character. Where the spoken name matters, write the key as a word, like Ctrl or esc.
  • An icon inside a key gives a screen reader no text to read, so where the key matters to the shortcut, use a character like ↑ instead.
  • It is not interactive and does not move. It takes no focus, pointer-events-none passes a click through to the button or row beneath it, and select-none leaves it out of a text selection.
  • A key inside a button or a command row becomes part of that control's accessible name. To keep the name to the action, set aria-hidden on the KbdGroup, and name the shortcut with aria-keyshortcuts on the control, like aria-keyshortcuts="Meta+K", for assistive tech that reads it.
  • In forced colors the system paints over the fill, and the key has no border, so it shows as plain text there.

When to use something else

  • The shortcut prop on a Menu item, for a shortcut at the end of a menu row. It takes a string and sets it as faint text with no chip, and Dropdown menu and Context menu do the same with DropdownMenuShortcut and ContextMenuShortcut.

Install

shadcn add @gesso/kbd

On this page