Kbd
A keycap sketched as a small box with a heavier bottom edge.
⌘K
Press Ctrl+Shift+P to open the command palette.
import { Kbd, KbdGroup } from "@/components/ui/kbd";
export default function KbdDemo() {
return (
<div className="flex flex-col gap-5">
<KbdGroup>
<Kbd seed="kbd-cmd">⌘</Kbd>
<Kbd seed="kbd-k">K</Kbd>
</KbdGroup>
<p className="text-ink-2">
Press{" "}
<KbdGroup>
<Kbd seed="kbd-ctrl">Ctrl</Kbd>
<span>+</span>
<Kbd seed="kbd-shift">Shift</Kbd>
<span>+</span>
<Kbd seed="kbd-p">P</Kbd>
</KbdGroup>{" "}
to open the command palette.
</p>
</div>
);
}Installation
pnpm dlx shadcn@latest add @ballpoint/ kbdOr copy the source
"use client";
import type { ComponentProps } from "react";
import { cn } from "@/lib/utils";
import { usePen, type Pen } from "@/hooks/use-ink-box";
import { Stroke } from "@/lib/ink";
import { InkOutline } from "@/lib/ink-outline";
import { lineStroke } from "@/lib/ink-sketch";
/** A keycap sketched as a small box with a heavier bottom edge. */
function Kbd({
className,
seed,
roughness,
radius,
draw,
weight,
speed,
...props
}: ComponentProps<"kbd"> & Pick<Pen, "roughness" | "radius" | "draw" | "weight" | "speed"> & { seed?: string | number }) {
const pen = usePen({ roughness, radius: radius ?? 4, draw, weight, speed, passes: 1, corners: "joined" });
return (
<kbd
data-slot="kbd"
className={cn(
"pointer-events-none relative inline-flex h-6 w-fit min-w-6 items-center justify-center gap-1 px-1.5 font-sans text-sm text-ink-2 select-none [&_svg:not(.ink-sketch):not([class*='size-'])]:size-3.5",
className,
)}
{...props}
>
<InkOutline pen={pen} seed={seed} estimate={[24, 24]} pad={5} className="text-ink-3">
{({ w, h, s }) => <Stroke d={lineStroke(s + 30, [1.5, h + 1.4], [w - 1, h + 1.2], { bow: 0.4, jitter: 0.2 })} draw={pen.draw ?? "auto"} delay={260} duration={200} width={1.6} />}
</InkOutline>
{props.children}
</kbd>
);
}
function KbdGroup({ className, ...props }: ComponentProps<"kbd">) {
return <kbd data-slot="kbd-group" className={cn("inline-flex items-center gap-1.5 font-sans", className)} {...props} />;
}
export { Kbd, KbdGroup };Usage
import { Kbd, KbdGroup } from "@/components/ui/kbd"
<KbdGroup>
<Kbd>⌘</Kbd>
<Kbd>K</Kbd>
</KbdGroup>API reference
- children
ReactNode - The key: a letter, a word, or an icon.
- KbdGroup
component - Sets keys pressed together side by side, in the hand.
- seed
string | number - Pins the drawing.
Pen settings
The drawing also takes draw, roughness, radius, weight and speed, as props or from the nearest InkProvider. What each one does.