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.

PropDefaultType
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