VisorVisor
ComponentsAdmin

Kbd

Tiny primitive for rendering keyboard shortcuts using the semantic <kbd> element. Supports a single key via children or a multi-key sequence via the keys prop with a customizable separator. Built with CSS Modules — copy it into your project and own it completely.

Single Key

K

Multi-Key Combo

K

Custom Separator

GP

Sizes

KKK

Variants

KK

Inline With Text

Press K to open the command palette.

Installation

npx visor add kbd

This copies two files into your project:

  • components/ui/kbd/kbd.tsx — the component
  • components/ui/kbd/kbd.module.css — the styles

Usage

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

export default function Example() {
  return (
    <p>
      Press <Kbd keys={['', 'K']} /> to open the command palette.
    </p>
  );
}

API Reference

KbdProps

PropTypeDefaultDescription
childrenReact.ReactNodeSingle-key content rendered inside the <kbd>. Ignored when `keys` is provided.
keysstring[]If provided, renders each key as its own <kbd> joined by `separator`. Mutually exclusive with `children` — `keys` wins if both are passed.
separatorReact.ReactNode'+'Separator rendered between keys in a multi-key sequence. Wrapped in an aria-hidden span so screen readers read each <kbd> on its own.
size'sm' | 'md' | 'lg''md'Controls padding and font-size of each key cap.
variant'default' | 'outline''default'Default uses a filled muted surface; outline is transparent with a border only.
classNamestringAdditional CSS class names merged onto the root element (the single <kbd> or, in multi-key mode, the wrapper <span>).
...propsReact.HTMLAttributes<HTMLElement>All standard HTML attributes are forwarded to the root element.

The component also accepts all standard HTML attributes for the root <kbd> (single-key) or wrapper <span> (multi-key) element.

Source Files

After running npx visor add kbd, you'll have:

kbd.tsx

A forwardRef component using CVA for size and variant. When keys is omitted it renders a single semantic <kbd> element with the variant chrome. When keys is provided it renders a layout-only wrapper <span> containing one <kbd> per key, joined by an aria-hidden separator span. The variant classes are applied to each inner <kbd> so each key gets its own raised key cap rendering — the wrapper itself stays unstyled.

kbd.module.css

All values use CSS custom properties from @loworbitstudio/visor-core, so the kbd automatically adapts to your active theme. The "raised key cap" elevation comes from var(--shadow-xs) rather than an inline rgba() shadow, and the monospace face uses var(--font-family-mono) with a system fallback stack.

Customization

After copying the component, you own it completely. Common customizations:

  • Add a link variant that wraps the <kbd> in an <a> for clickable shortcuts.
  • Extend variants to include a subtle style for use inside dark tooltips.
  • Swap box-shadow for a heavier "double border" key cap look if you want a more skeuomorphic feel.