Kbd

Kbd shows a keyboard key, so a shortcut like ⌘K reads as keys and not as text.

⌘KCtrlCShiftTabEnterEsc
import { Kbd, KbdGroup } from "@/components/ui/kbd";

export default function KbdDemo() {
  return (
    <>
      <KbdGroup>
        <Kbd aria-label="Command">⌘</Kbd>
        <Kbd>K</Kbd>
      </KbdGroup>
      <KbdGroup>
        <Kbd>Ctrl</Kbd>
        <Kbd>C</Kbd>
      </KbdGroup>
      <KbdGroup>
        <Kbd>Shift</Kbd>
        <Kbd>Tab</Kbd>
      </KbdGroup>
      <Kbd>Enter</Kbd>
      <Kbd>Esc</Kbd>
    </>
  );
}

The code

The component is a single file, read from the repository when the site is built. Press Show code to see all of it.

import type { ComponentProps } from "react";
import { cx } from "@/lib/cx";

// One keyboard key. It is the native kbd element, so it keeps its meaning for assistive tech.
export function Kbd({ className, ...props }: ComponentProps<"kbd">) {
  return (
    <kbd
      className={cx(
        "inline-flex h-6 min-w-6 items-center justify-center rounded-sm border border-border-strong bg-surface px-1.5 font-mono text-xs font-medium text-text",
        className,
      )}
      {...props}
    />
  );
}

// Keys that are pressed together, such as Command and K.
export function KbdGroup({ className, ...props }: ComponentProps<"span">) {
  return <span className={cx("inline-flex items-center gap-1", className)} {...props} />;
}

Props

PropTypeDefaultWhat it does
classNamestring—On Kbd and KbdGroup. Extra classes, added after the component's own.

Kbd is the native kbd element and KbdGroup is a span, so both take every normal prop, such as aria-label.

The thinking

A shortcut is easier to spot and to remember when each key looks like a key.

  • The real element: Kbd renders the native kbd element, which tells assistive tech that the text is input from a keyboard.
  • One key each: Put each key in its own Kbd, and wrap keys that are pressed together in a KbdGroup.
  • Show it where it applies: Place a shortcut next to the control or command it triggers, such as in a button or a menu item.

Interface design

  • Key: At least 24px wide and exactly 24px tall, with the sm radius, 4px, the surface fill and a strong 1px border.
  • Text: 12px medium, in the mono face, in the main text color.
  • Group: Keys in a KbdGroup sit 4px apart.

Interaction

  • Display only: A key has no hover, focus or pressed state, and can't be focused. It shows a shortcut but doesn't create one, so you still have to handle the keys yourself.

Empathy

  • Name the symbols: Screen readers don't all read a symbol like ⌘ the same way. Give it an aria-label such as Command, as the demo does.
  • Contrast: The text is 14.2:1 against the key's fill.
  • Don't hide the action: A shortcut is a shortcut, not the only way in. The action behind it should also have a visible control.