Agents (llms.txt)
Octocat

Kbd

A keyboard key indicator for displaying shortcuts and key bindings.

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

export default function KbdPreview() {
  return (
    <Kbd.Group>
      <Kbd></Kbd>
      <Kbd>K</Kbd>
    </Kbd.Group>
  );
}

Dependencies

Source Code

import type { VariantProps } from 'cva';

import { Slot } from '@/components/slot';
import { cn, cva } from '@/lib/utils/classnames';

const kbdStyle = cva({
  base: [
    'inline-flex h-(--kbd-height) min-w-(--kbd-height) shrink-0 items-center justify-center',
    'rounded-md border border-border bg-background-secondary',
    'font-mono text-foreground leading-none',
    // 2px hard shadow visually weighs the bottom; lift 1px to optically center
    // against surrounding text.
    '-translate-y-px shadow-[0_2px_0_0_var(--color-border)]',
  ],
  variants: {
    size: {
      sm: 'px-1 text-2xs [--kbd-height:--spacing(4)]',
      md: 'px-1.5 text-xs [--kbd-height:--spacing(5)]',
      lg: 'px-2 text-sm [--kbd-height:--spacing(6)]',
    },
  },
  defaultVariants: {
    size: 'md',
  },
});

interface KbdProps extends React.ComponentPropsWithRef<'kbd'> {
  size?: VariantProps<typeof kbdStyle>['size'];
  asChild?: boolean;
}

const Kbd = ({
  ref,
  children,
  size = 'md',
  className,
  asChild,
  ...rest
}: KbdProps) => {
  const Comp = asChild ? Slot : 'kbd';

  return (
    <Comp ref={ref} className={cn(kbdStyle({ size }), className)} {...rest}>
      {children}
    </Comp>
  );
};

const KbdGroup = ({
  className,
  children,
  ...rest
}: React.ComponentPropsWithRef<'span'>) => {
  return (
    <span
      className={cn('inline-flex items-center gap-1 align-middle', className)}
      {...rest}
    >
      {children}
    </span>
  );
};

const CompoundKbd = Object.assign(Kbd, {
  Group: KbdGroup,
});

export { CompoundKbd as Kbd };

Anatomy


          <Kbd />

<Kbd.Group>
  <Kbd />
  <Kbd />
</Kbd.Group>
        

API Reference

Kbd

Extends the kbd element.

Prop Default Type
size "md" "sm""md""lg"
asChild - boolean

Kbd.Group

Extends the span element. Wraps multiple Kbds with consistent spacing and alignment so they read as a single shortcut.

Examples

Sizes

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

export default function KbdSizesPreview() {
  return (
    <div className="flex items-center gap-4">
      <Kbd size="sm"></Kbd>
      <Kbd size="md"></Kbd>
      <Kbd size="lg"></Kbd>
    </div>
  );
}

Inline in text

Press P to open the command palette, or Esc to close it.

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

export default function KbdInlinePreview() {
  return (
    <p className="text-foreground-secondary text-sm">
      Press{' '}
      <Kbd.Group>
        <Kbd></Kbd>
        <Kbd></Kbd>
        <Kbd>P</Kbd>
      </Kbd.Group>{' '}
      to open the command palette, or <Kbd>Esc</Kbd> to close it.
    </p>
  );
}

OS-aware shortcuts

Kbd is a presentational element — it renders whatever you put inside. For OS-aware rendering ( on macOS, Ctrl elsewhere), detect the platform once at the top of your tree and pass the right symbol:


          const isMac = typeof navigator !== "undefined" && navigator.platform.toLowerCase().includes("mac");
const modKey = isMac ? "⌘" : "Ctrl";

<Kbd.Group>
  <Kbd>{modKey}</Kbd>
  <Kbd>K</Kbd>
</Kbd.Group>;
        

Common Mac glyphs: Command, Option, Control, Shift, Return, Delete, Escape, Tab.

Best Practices

  1. Usage:

    • Wrap multi-key shortcuts in Kbd.Group so spacing and alignment stay consistent.
    • Keep contents to a single key or short label (Esc, Tab) — long words should be regular text.
  2. Accessibility:

    • The <kbd> element is read by screen readers as keyboard input. Don’t override the role.
    • Provide written context next to the shortcut so it’s discoverable without sight (e.g., “Press ⌘K to search”).

Previous

Input

Next

Listbox