Kbd
A keyboard key indicator for displaying shortcuts and key bindings.
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
-
Usage:
- Wrap multi-key shortcuts in
Kbd.Groupso spacing and alignment stay consistent. - Keep contents to a single key or short label (
Esc,Tab) — long words should be regular text.
- Wrap multi-key shortcuts in
-
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”).
- The
Previous
Input
Next
Listbox