ComponentsText effects
Brush Annotation
Hand-brushed ink marks over inline text: underline, double underline, circle, strike, bracket and highlight.
Field notes
"use client";
import { RotateCcw } from "lucide-react";
import { useState } from "react";
import { BrushAnnotation } from "@/components/miyuki-ui/brush-annotation";
import { Button } from "@/components/miyuki-ui/button";
export default function BrushAnnotationDemo() {
const [run, setRun] = useState(0);
return (
<div className="w-full max-w-xl">
<p className="text-sm text-muted-foreground">Field notes · Hakuba, 14 February</p>
<p key={run} className="mt-3 text-lg leading-9 text-foreground text-pretty">
Snow began at four and fell{" "}
<BrushAnnotation kind="underline" delay={150}>
steadily until noon
</BrushAnnotation>
. The north bowl held{" "}
<BrushAnnotation kind="highlight" color="var(--chart-2)" delay={800}>
38 cm of new powder
</BrushAnnotation>
, dry and light at −9 °C. Patrol kept the{" "}
<BrushAnnotation kind="circle" delay={1450}>
Happo ridge
</BrushAnnotation>{" "}
closed until half past ten. The forecast promised{" "}
<BrushAnnotation kind="strike" color="var(--destructive)" delay={2250}>
clearing by afternoon
</BrushAnnotation>
; it never cleared.{" "}
<BrushAnnotation kind="bracket" delay={2850}>
Skins on at one, back at the hut by three.
</BrushAnnotation>
</p>
<Button
variant="ghost"
size="sm"
className="mt-4 -ml-3"
iconStart={<RotateCcw />}
onPress={() => setRun((r) => r + 1)}
>
Draw again
</Button>
</div>
);
}Kinds
"use client";
import { useState } from "react";
import { BrushAnnotation, type BrushAnnotationKind } from "@/components/miyuki-ui/brush-annotation";
import { Switch } from "@/components/miyuki-ui/switch";
const kinds: { kind: BrushAnnotationKind; text: string; color?: string }[] = [
{ kind: "underline", text: "Last lift at 16:30" },
{ kind: "double", text: "Chains required" },
{ kind: "circle", text: "Gate 4" },
{ kind: "strike", text: "Open all day", color: "var(--destructive)" },
{ kind: "bracket", text: "Hut closed Mondays" },
{ kind: "highlight", text: "Fresh tracks", color: "var(--chart-2)" },
];
export default function BrushAnnotationKindsDemo() {
const [show, setShow] = useState(true);
return (
<div className="flex w-full max-w-2xl flex-col items-center gap-8">
<div className="grid w-full grid-cols-1 gap-x-10 gap-y-7 text-xl text-foreground sm:grid-cols-2">
{kinds.map((k, i) => (
<div key={k.kind} className="flex items-baseline gap-4">
<span className="w-20 shrink-0 text-xs text-muted-foreground">{k.kind}</span>
<span>
<BrushAnnotation kind={k.kind} color={k.color} show={show} delay={i * 220}>
{k.text}
</BrushAnnotation>
</span>
</div>
))}
</div>
<Switch size="sm" isSelected={show} onChange={setShow}>
Show marks
</Switch>
</div>
);
}Install
npx shadcn@latest add @miyuki-ui/brush-annotationThis needs the @miyuki-ui registry in your components.json. See Using the shadcn CLI.
Props
BrushAnnotation
Prop
Type