Qure UI
Components

Kbd

A keyboard key, as the element that actually means one.

Press N to jump to the next unread study, or Esc to return to the worklist.

'use client'import { Kbd, KbdGroup } from '@/registry/qure/ui/kbd'export default function KbdDemo() {  return (    <p className="max-w-sm text-center text-sm text-muted-foreground">      Press{' '}      <KbdGroup>        <Kbd>⇧</Kbd>        <Kbd>N</Kbd>      </KbdGroup>{' '}      to jump to the next unread study, or <Kbd>Esc</Kbd> to return to the worklist.    </p>  )}

Installation

npx shadcn@latest add https://qure-ui.qure.ai/r/kbd.json

Usage

import { Kbd, KbdGroup } from '@/components/ui/kbd'
<KbdGroup>
  <Kbd>⌘</Kbd>
  <Kbd>K</Kbd>
</KbdGroup>

<kbd> is one of the few elements that says something a <span> cannot: this is a key you press. There is no behaviour to own and no Base UI primitive, only semantics and a look — which is exactly why it is easy to skip and worth not skipping.

Chords and sequences

Window / level
W
Zoom
Z
Pan
P
Invert greyscale
I
Sign report
'use client'import { Kbd, KbdGroup } from '@/registry/qure/ui/kbd'const shortcuts = [  { keys: ['W'], action: 'Window / level' },  { keys: ['Z'], action: 'Zoom' },  { keys: ['P'], action: 'Pan' },  { keys: ['⇧', 'I'], action: 'Invert greyscale' },  { keys: ['⌘', '⏎'], action: 'Sign report' },]/** * The shortcut sheet a viewer shows on `?`. Each combination is several `Kbd` * elements rather than one string, so "Command Return" is read as two keys. */export default function KbdViewer() {  return (    <dl className="grid w-full max-w-sm grid-cols-[1fr_auto] items-center gap-x-6 gap-y-3">      {shortcuts.map(shortcut => (        <div key={shortcut.action} className="contents">          <dt className="text-sm text-foreground">{shortcut.action}</dt>          <dd className="justify-self-end">            <KbdGroup>              {shortcut.keys.map(key => (                <Kbd key={key}>{key}</Kbd>              ))}            </KbdGroup>          </dd>        </div>      ))}    </dl>  )}

Write a combination as several Kbd elements inside a KbdGroup, not one string. ⌘⏎ in a single element is announced as two unfamiliar symbols; <Kbd>⌘</Kbd><Kbd>⏎</Kbd> is announced as two keys, which is what it is.

Nesting Kbd inside Kbd is also valid HTML and is what the spec suggests for a combination, but the group is easier to style: it carries the spacing and keeps the caps from touching.

Variants

key — a drawn cap, for proseW
plain — bare glyphs, the way Figma draws a menu shortcut⌘⇧W
'use client'import { Kbd, KbdGroup } from '@/registry/qure/ui/kbd'export default function KbdVariant() {  return (    <div className="flex flex-col items-center gap-6">      <div className="flex flex-col items-center gap-2">        <span className="text-xs text-muted-foreground">key — a drawn cap, for prose</span>        <KbdGroup>          <Kbd>⌘</Kbd>          <Kbd>⇧</Kbd>          <Kbd>W</Kbd>        </KbdGroup>      </div>      <div className="flex flex-col items-center gap-2">        <span className="text-xs text-muted-foreground">          plain — bare glyphs, the way Figma draws a menu shortcut        </span>        <Kbd variant="plain">⌘⇧W</Kbd>      </div>    </div>  )}

key draws a cap and is the default — use it when the key stands on its own in a sentence. plain is bare glyphs, which is how Figma draws a menu shortcut.

In a menu

'use client'import { MoreHorizontalIcon } from 'lucide-react'import { Button } from '@/registry/qure/ui/button'import {  DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuShortcut,  DropdownMenuTrigger,} from '@/registry/qure/ui/dropdown-menu'import { Kbd } from '@/registry/qure/ui/kbd'/** * Inside a menu, use `variant="plain"` — Figma's "Menu Shortcut" is bare * glyphs, and a drawn key cap fights the row's brand fill on hover. The * `<kbd>` element still does its job: the row announces as a command with a * key, not as a command with a stray symbol after it. */export default function KbdMenu() {  return (    <DropdownMenu>      <DropdownMenuTrigger        render={          <Button variant="tertiary" size="icon-md" aria-label="Viewer actions">            <MoreHorizontalIcon className="size-4" />          </Button>        }      />      <DropdownMenuContent className="min-w-64">        <DropdownMenuItem>          Next unread study          <DropdownMenuShortcut>            <Kbd variant="plain">⇧N</Kbd>          </DropdownMenuShortcut>        </DropdownMenuItem>        <DropdownMenuItem>          Toggle AI heatmap          <DropdownMenuShortcut>            <Kbd variant="plain">⇧H</Kbd>          </DropdownMenuShortcut>        </DropdownMenuItem>        <DropdownMenuItem>          Sign report          <DropdownMenuShortcut>            <Kbd variant="plain">⌘⏎</Kbd>          </DropdownMenuShortcut>        </DropdownMenuItem>      </DropdownMenuContent>    </DropdownMenu>  )}

Reach for variant="plain" inside a menu row. A drawn cap fights the row's brand fill on hover, and the shortcut is meant to be read as a hint rather than as a control. The <kbd> element still earns its place: the row announces as a command with a key attached, not as a command with a stray symbol after it.

Size

sm1
md1
'use client'import { Kbd, KbdGroup } from '@/registry/qure/ui/kbd'export default function KbdSize() {  return (    <div className="flex items-end gap-8">      <div className="flex flex-col items-center gap-2">        <span className="text-xs text-muted-foreground">sm</span>        <KbdGroup>          <Kbd size="sm">⌥</Kbd>          <Kbd size="sm">1</Kbd>        </KbdGroup>      </div>      <div className="flex flex-col items-center gap-2">        <span className="text-xs text-muted-foreground">md</span>        <KbdGroup>          <Kbd size="md">⌥</Kbd>          <Kbd size="md">1</Kbd>        </KbdGroup>      </div>    </div>  )}

sm is the default and matches body text. md is for a shortcut sheet or a hero hint where the key is the subject of the line rather than an aside.

Use the platform's own glyphs — ⌘ ⇧ ⌥ ⏎ ⌫ — rather than spelling out "Cmd" or "Shift". They are what is printed on the keys, and macOS users match them by shape. If you support Windows, branch on the platform rather than writing Ctrl/⌘, which is a key nobody has.

API Reference

Kbd

Renders a <kbd>.

PropTypeDefaultDescription
variant"key" | "plain""key"key draws a cap; plain is bare glyphs.
size"sm" | "md""sm"sm matches body text.

KbdGroup

Renders a <span>. Takes no props of its own beyond the usual span props.

On this page