# Kbd (/docs/kbd)





`Kbd` is a non-interactive `<kbd>` styled with the kit's (variant × color) system. The shape and palette axes are the exact set [`Button`](/docs/button) exposes, so a shortcut hint speaks the same accent language as the action it labels — but without hover or click behavior.

```tsx
import { Kbd } from '@42-central/ui-react/kbd';

<Kbd>⌘</Kbd>
<Kbd>⌘K</Kbd>
<Kbd variant="light" color="brand">Enter</Kbd>
```

## Playground [#playground]

<story.Playground />

### Full prop browser [#full-prop-browser]

<story.WithControl />

## Variants [#variants]

The five shape treatments are exactly the set [`Button`](/docs/button) uses. The default variant is `default` — the neutral, bordered key cap that reads as a physical key: a translucent fill that adapts to whatever surface it sits on, a hairline border, and a 1px shade along the bottom edge for the lip of a real key.

<Preview align="block" code="&#x22;<Kbd variant=\&#x22;default\&#x22;>⌘</Kbd>\n<Kbd variant=\&#x22;filled\&#x22;>⌘</Kbd>\n<Kbd variant=\&#x22;light\&#x22;>⌘</Kbd>\n<Kbd variant=\&#x22;outline\&#x22;>⌘</Kbd>\n<Kbd variant=\&#x22;subtle\&#x22;>⌘</Kbd>&#x22;">
  <div className="flex flex-wrap items-center gap-2">
    <Kbd variant="default">
      ⌘
    </Kbd>

    <Kbd variant="filled">
      ⌘
    </Kbd>

    <Kbd variant="light">
      ⌘
    </Kbd>

    <Kbd variant="outline">
      ⌘
    </Kbd>

    <Kbd variant="subtle">
      ⌘
    </Kbd>
  </div>
</Preview>

`default` is palette-independent — `color` is ignored for fill/text on this variant.

## Colors [#colors]

Any palette color pairs with any variant except `default`. Reach for a color when the key belongs to a colored action (a green confirm, a red destructive shortcut).

<Preview align="block" code="&#x22;<Kbd variant=\&#x22;light\&#x22;  color=\&#x22;green\&#x22;>↵</Kbd>\n<Kbd variant=\&#x22;filled\&#x22; color=\&#x22;red\&#x22;>⌫</Kbd>\n<Kbd variant=\&#x22;outline\&#x22; color=\&#x22;blue\&#x22;>Tab</Kbd>&#x22;">
  <div className="flex flex-col gap-2">
    <div className="flex flex-wrap gap-2">
      {COLORS.map((c) => (
              <Kbd key={c} variant="light" color={c}>
                {c[0].toUpperCase()}
              </Kbd>
            ))}
    </div>

    <div className="flex flex-wrap gap-2">
      {COLORS.map((c) => (
              <Kbd key={c} variant="filled" color={c}>
                {c[0].toUpperCase()}
              </Kbd>
            ))}
    </div>
  </div>
</Preview>

## Sizes [#sizes]

Each size steps the type by one Tailwind step — `sm` 12px, `md` 14px, `lg` 16px — so pick the one that matches the text the key sits beside: `sm` inside a `Button` or a search field, `md` in body copy. Single-character keys stay square (a per-size `min-w` equal to the height); wider labels grow horizontally. An icon inside a key draws a 1.5px stroke at every size.

<Preview align="block" code="&#x22;<Kbd size=\&#x22;sm\&#x22;>⌘</Kbd>\n<Kbd size=\&#x22;md\&#x22;>⌘</Kbd>\n<Kbd size=\&#x22;lg\&#x22;>⌘</Kbd>&#x22;">
  <KbdSizesDemo />
</Preview>

## In context [#in-context]

A `Kbd` slots cleanly into a `Button` to surface its shortcut. The button drives layout; the key cap stays neutral.

<Preview align="center" code="&#x22;<Button variant=\&#x22;outline\&#x22; color=\&#x22;neutral\&#x22; startSlot={<Plus />} endSlot={<Kbd size=\&#x22;sm\&#x22;>⌘N</Kbd>}>\n  New file\n</Button>&#x22;">
  <Button variant="outline" color="neutral" startSlot="<Plus />" endSlot="<Kbd size=&#x22;sm&#x22;>⌘N</Kbd>">
    New file
  </Button>
</Preview>

## Composing chords [#composing-chords]

A chord is just a row of keys. Render one `Kbd` per key and separate them with a `+`:

<Preview align="center" code="&#x22;<span className=\&#x22;inline-flex items-center gap-1\&#x22;>\n  <Kbd>⌘</Kbd> + <Kbd>⇧</Kbd> + <Kbd>P</Kbd>\n</span>&#x22;">
  <span className="inline-flex items-center gap-1 font-mono text-sm">
    <Kbd>⌘</Kbd> + <Kbd>⇧</Kbd> + <Kbd>P</Kbd>
  </span>
</Preview>

## API [#api]

<TypeTable
  type="{
  variant: {
    type: &#x22;'filled' | 'light' | 'outline' | 'subtle' | 'default'&#x22;,
    default: &#x22;'default'&#x22;,
    description: &#x22;Visual treatment. Shares Button's set.&#x22;,
  },
  color: {
    type: &#x22;'brand' | 'neutral' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'cyan' | 'blue' | 'purple' | 'pink' | (string & {})&#x22;,
    default: &#x22;'brand'&#x22;,
    description:
      'Accent palette. Ignored by the default variant. Custom values work as long as a matching [data-color=&#x22;…&#x22;] block exists in colors.css.',
  },
  size: {
    type: &#x22;'sm' | 'md' | 'lg'&#x22;,
    default: &#x22;'md'&#x22;,
    description: &#x22;Height + min-width + text scale (12 / 14 / 16px).&#x22;,
  },
  asChild: {
    type: &#x22;boolean&#x22;,
    default: &#x22;false&#x22;,
    description: &#x22;Render children as the root element (Ark UI polymorphism).&#x22;,
  },
}"
/>

All other props are forwarded to the underlying `<kbd>` (or `asChild` element).

## Accessibility [#accessibility]

`Kbd` renders a semantic `<kbd>` element, the right markup for user input / keyboard keys. It is a display element — no hover treatment, no click handling. If a key should be operable (a clickable shortcut row), use `asChild` with a real `<button>` so semantics line up; the kit's [focus ring](/docs/focus) rides along, so the key is keyboard-visible without any `className` of your own:

```tsx
<Kbd asChild>
  <button type="button" onClick={openPalette}>
    ⌘K
  </button>
</Kbd>
```
