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