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
| Prop | Type | Default | What it does |
|---|---|---|---|
className | string | — | 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-labelsuch 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.