Kbd
Keys, for documenting a shortcut.
import { Div, Span } from "@implementjs/core";
import { Kbd, KbdGroup } from "@/lib/components/ui/kbd";
export default function KbdDemo() {
return Div(
{ class: "flex flex-col items-center gap-3 text-sm" },
Div(
{ class: "flex items-center gap-2" },
Span({ class: "text-muted-foreground" }, "Open search"),
KbdGroup(Kbd("⌘"), Kbd("K")),
),
Div(
{ class: "flex items-center gap-2" },
Span({ class: "text-muted-foreground" }, "Toggle the sidebar"),
KbdGroup(Kbd("Ctrl"), Kbd("B")),
),
Div(
{ class: "flex items-center gap-2" },
Span({ class: "text-muted-foreground" }, "Then press"),
KbdGroup(Kbd("G"), Span({ class: "text-muted-foreground" }, "then"), Kbd("H")),
),
);
}Installation
npx jsrepo add @implementjs/ui/kbd
Nothing else comes with it — this one stands alone on @implementjs/core and @implementjs/primitives.
Copy the file below to src/lib/components/ui/kbd.ts. It imports cn, so copy utils.ts to src/lib/utils.ts too.
import { Kbd as KbdElement, type Child, type ElementProps } from "@implementjs/core";
import { createComponent } from "@implementjs/primitives";
import { cn } from "@/lib/utils";
export type KbdProps = ElementProps<"kbd">;
export type KbdGroupProps = ElementProps<"kbd">;
/** One key on a keyboard, for documenting a shortcut. */
export const Kbd = createComponent(function Kbd(
{ class: className, ...props }: KbdProps,
...children: Child[]
) {
return KbdElement(
{
...props,
"data-slot": "kbd",
class: cn(
"inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1",
"font-sans text-[0.7rem] font-medium text-muted-foreground select-none",
"[&_svg:not([class*='size-'])]:size-3",
"[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
className,
),
},
...children,
);
});
/** A chord or a sequence: several keys read as one shortcut. */
export const KbdGroup = createComponent(function KbdGroup(
{ class: className, ...props }: KbdGroupProps,
...children: Child[]
) {
return KbdElement(
{
...props,
"data-slot": "kbd-group",
class: cn("inline-flex items-center gap-1", className),
},
...children,
);
});Usage
import { Kbd, KbdGroup } from "@/lib/components/ui/kbd";
KbdGroup(Kbd("⌘"), Kbd("K"));
Kbd is one key. KbdGroup is a chord or a sequence read as one shortcut — it keeps the keys on the same line with an even gap.
Inside a tooltip
A shortcut is often shown next to what it does, in a tooltip. The muted grey a key uses on the page has no contrast on a tooltip's inverted panel, so Kbd detects that it is inside one and flips its own colors:
TooltipContent("Toggle the sidebar", KbdGroup(Kbd("⌘"), Kbd("B")));
Nothing to pass — the rule keys off [data-slot=tooltip-content] on an ancestor.
Sequences
For a two-step shortcut, put the connecting word between the keys rather than inside one:
KbdGroup(Kbd("G"), Span({ class: "text-muted-foreground" }, "then"), Kbd("H"));
API Reference
Kbd
One key, for documenting a shortcut. Renders a Kbd; extra props are forwarded onto it.
KbdGroup
A chord or a sequence: several keys read as one shortcut. Renders a Kbd; extra props are forwarded onto it.