Kbd

Keyboard key and shortcut display component with a realistic keycap style.

Made by Léo
Open in
Esc
Save fileS
Open command menuK
UndoZ
Find & replaceH
demo-kbd.tsx
"use client";

import { Kbd, Shortcut } from "@/components/unlumen-ui/kbd";

export const KbdDemo = ({ size = "md" }: { size?: "sm" | "md" | "lg" }) => {
  return (
    <div className="flex flex-col items-center justify-center gap-6 p-8">
      {/* Single keys */}
      <div className="flex flex-wrap items-center justify-center gap-2">
        {["⌘", "⌥", "⇧", "⌃", "⏎", "⌫", "⇥", "Esc"].map((key) => (
          <Kbd key={key} size={size}>
            {key}
          </Kbd>
        ))}
      </div>

      {/* Common shortcuts */}
      <div className="flex flex-col gap-3 text-sm text-muted-foreground">
        <div className="flex items-center justify-between gap-8">
          <span>Save file</span>
          <Shortcut keys={["⌘", "S"]} size={size} />
        </div>
        <div className="flex items-center justify-between gap-8">
          <span>Open command menu</span>
          <Shortcut keys={["⌘", "K"]} size={size} />
        </div>
        <div className="flex items-center justify-between gap-8">
          <span>Undo</span>
          <Shortcut keys={["⌘", "Z"]} size={size} />
        </div>
        <div className="flex items-center justify-between gap-8">
          <span>Find &amp; replace</span>
          <Shortcut keys={["⌘", "⇧", "H"]} size={size} />
        </div>
      </div>
    </div>
  );
};

Installation

Copy and paste the following code into your project:

components/unlumen-ui/kbd.tsx
import { Fragment, type HTMLAttributes, type ReactNode } from "react";
import { cn } from "@/lib/utils";

type KbdSize = "sm" | "md" | "lg";

interface KbdProps extends HTMLAttributes<HTMLElement> {
  size?: KbdSize;
  children: ReactNode;
}

interface ShortcutProps extends HTMLAttributes<HTMLSpanElement> {
  keys: string[];
  separator?: ReactNode;
  size?: KbdSize;
}

function Kbd({ size = "md", children, className, ...props }: KbdProps) {
  const sizeClass: Record<KbdSize, string> = {
    sm: "h-5 min-w-5 px-1 text-[10px]",
    md: "h-6 min-w-6 px-1.5 text-[11px]",
    lg: "h-7 min-w-7 px-2 text-[12px]",
  };

  return (
    <kbd
      className={cn(
        "inline-flex items-center justify-center rounded border font-mono font-medium leading-none select-none",
        "border-b-2 border-border bg-muted text-muted-foreground",
        "shadow-[inset_0_-1px_0_rgba(0,0,0,0.08)]",
        sizeClass[size],
        className,
      )}
      {...props}
    >
      {children}
    </kbd>
  );
}

function Shortcut({
  keys,
  separator = "+",
  size = "md",
  className,
  ...props
}: ShortcutProps) {
  return (
    <span
      className={cn("inline-flex items-center gap-0.5", className)}
      aria-label={keys.join(separator === "+" ? " + " : " then ")}
      {...props}
    >
      {keys.map((key, i) => (
        <Fragment key={key}>
          <Kbd size={size}>{key}</Kbd>
          {i < keys.length - 1 && (
            <span
              className="text-muted-foreground/60 text-[10px] font-medium px-0.5"
              aria-hidden
            >
              {separator}
            </span>
          )}
        </Fragment>
      ))}
    </span>
  );
}

export { Kbd, Shortcut };
export type { KbdProps, ShortcutProps, KbdSize };

Update the import paths to match your project setup.

Usage

import { Kbd, Shortcut } from "@/components/unlumen-ui/kbd";
// Single key
<Kbd>⌘</Kbd>
<Kbd>Enter</Kbd>

// Shortcut combo
<Shortcut keys={["⌘", "K"]} />
<Shortcut keys={["⌘", "⇧", "P"]} />

Props

Kbd

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Size of the key cap.
childrenReactNodeThe key label (text or symbol).
classNamestringExtra classes on the kbd element.

Shortcut

PropTypeDefaultDescription
keysstring[]Ordered list of keys in the shortcut.
separatorReactNode"+"Separator displayed between keys.
size"sm" | "md" | "lg""md"Size passed to each Kbd.
classNamestringExtra classes on the wrapper span.

Built by Léo from Unlumen :3

Last updated: 3/15/2026