Kbd

Keyboard shortcut key caps.

import { Kbd }from "@/components/ui"

Specification

Renders one or more keyboard shortcut key caps.

Props (2)
Every prop this component accepts, its type, default, and how to use it.
PropTypeDefaultDescription
keys*string | string[]—A single key or an array of keys to render as separate caps (e.g. ["⌘", "K"]).
classNamestring—Extra classes merged onto the wrapper.

Shortcuts

Open search ⌘KClose EscSave ⌘S
Full source
The complete component, read from src/components/ui/kbd.tsx.
kbd.tsx
import { cn } from "@/lib/utils";

interface KbdProps {

  keys: string | string[];
  className?: string;
}

export function Kbd({ keys, className }: KbdProps) {
  const list = Array.isArray(keys) ? keys : [keys];
  return (
    <span className={cn("inline-flex items-center gap-1", className)}>
      {list.map((k, i) => (
        <kbd
          key={i}
          className="inline-flex h-5 min-w-5 items-center justify-center rounded border border-border bg-bg-secondary px-1.5 font-mono text-[11px] font-medium text-text-secondary"
        >
          {k}
        </kbd>
      ))}
    </span>
  );
}

Dependencies

To use Kbd you also need the following. Copy these into your project alongside it.

Recommended folder structure

project structure
src/components/ui/
  └─ kbd.tsx
src/lib/
  └─ utils.ts

Dependency files

These supporting files aren’t components — copy each one into the matching path above.

src/lib/utils.ts
utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

/**
 * Merge class names with clsx semantics + Tailwind conflict resolution.
 * Prefer this in all components.
 */
export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs));
}

/**
 * Concatenate class names, filtering out falsy values.
 * @deprecated Prefer {@link cn} — it also resolves Tailwind class conflicts.
 */
export function cx(...args: (string | false | null | undefined)[]): string {
  return args.filter(Boolean).join(" ");
}

/**
 * Focus ring style helper.
 * @deprecated Focus rings are now handled globally via the
 * `:focus-visible` rule in `globals.css` and the `focus-visible:*`
 * utilities. This remains only for backwards compatibility.
 */
export function ring(color: string = "var(--color-accent)") {
  return { outlineColor: color };
}