crucıble

Stencil

Canvas headline spray-painted through a cut stencil plate: seeded S-curve sweeps deposit grainy paint inside the letter cutouts with faint overspray and a few drips, then the plate lifts away to reveal the word; drag to add coats.

canvasfree

Installation

CLI

npx shadcn@latest add @crucible/stencil

Props

PropTypeDefaultDescription
textstring"STENCIL"The headline (also rendered as a visually hidden heading for screen readers + SEO).
as"h1" | "h2" | "h3" | "p""h2"Element the visually hidden real text is rendered as, so it stays a heading.
paintstring"#f2f0eb" (off-white)Spray paint color.
platestring"#2a2b2f" (graphite)Stencil plate color — keep it a little lighter than the surface behind it.
fontSizenumberauto (~48% of the height)Maximum glyph size in px; the headline scales down (and wraps to two lines) to fit.
fontFamilystringa bold condensed sans stack (Impact / Oswald / Arial Narrow…)Canvas font stack. Any counters (the holes in O, A, B…) get stencil bridges cut automatically, so plain bold fonts read as real stencils. Web fonts are picked up once document.fonts is ready.
passesnumber3Number of S-curve sweeps the can makes per line of text. 1–8.
dripsnumber5Paint runs that trickle 4–18px down from the letters' bottom edges during the intro. 0–16.
seednumber7Deterministic seed for the spray grain, sweep paths and drip spots.
refReact.Ref<StencilHandle>Imperative handle: replay().
Also accepts all props of Omit< React.HTMLAttributes<HTMLDivElement>, "children" | "color" > — they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, pauses offscreen and on hidden tabs, and passes className through.