Keycap Hint
Keyboard keys rendered as physical keycaps: mono type on a raised face with a thicker bottom border and an inset shadow for the sculpted dish, plus a Shortcut composer that joins chords with + and sequences with then, labeled for screen readers as one phrase instead of letter soup.
Micro InteractionReactTailwind CSS
CSSTailwind
Manual
Create a file and paste the following code into it.
keycap-hint.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"use client";
import { Fragment, type HTMLAttributes, type ReactNode } from "react";
import { cn } from "@/lib/cn";
/* ------------------------------------------------------------------ */
/* KeycapHint */
/* ------------------------------------------------------------------ */
type KeycapSize = "sm" | "md" | "lg";
interface KeycapProps extends HTMLAttributes<HTMLElement> {
size?: KeycapSize;
children: ReactNode;
}
interface ShortcutProps extends HTMLAttributes<HTMLSpanElement> {
keys: string[];
/** Joiner between keys — "+" for chords, "then" for sequences [Optional, default: "+"] */
separator?: ReactNode;
size?: KeycapSize;
}
const SIZE_CLASS: Record<KeycapSize, string> = {
sm: "h-5.5 min-w-5.5 px-1 text-[11px]",
md: "h-6 min-w-6 px-1.5 text-[12px]",
lg: "h-7 min-w-7 px-2 text-[13px]",
};
/**
* A keyboard key rendered as a physical keycap: mono type on a raised face
* with a thicker bottom border and an inset shadow for the sculpted dish.
* @param {KeycapSize} size - Cap size [Optional, default: "md"]
*/
export function Keycap({ size = "md", children, className, ...props }: KeycapProps) {
return (
<kbd
className={cn(
"inline-flex select-none items-center justify-center rounded border border-b-2 border-zinc-300 bg-zinc-100 font-mono font-medium leading-none text-zinc-600 shadow-[inset_0_-1px_0_rgba(0,0,0,0.08)] dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300",
SIZE_CLASS[size],
className,
)}
{...props}
>
{children}
</kbd>
);
}
/**
* A shortcut as a row of keycaps with a joiner, labeled for screen readers
* as one phrase ("meta + K") rather than letter soup.
* @param {string[]} keys - Keys in press order [Required]
*/
export 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}-${i}`}>
<Keycap size={size}>{key}</Keycap>
{i < keys.length - 1 && (
<span aria-hidden className="px-0.5 text-[11px] font-medium text-zinc-400">
{separator}
</span>
)}
</Fragment>
))}
</span>
);
}
Update the import paths to match your project setup.
Similar components
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryMicro Interaction
ReactTailwind CSS
Install via CLI
Resource details
PublishedJuly 17, 2026
CategoryMicro Interaction
ReactTailwind CSS