Halden Type Foundry
Drift is a variable grotesk drawn in 9 weights and cut for screens that never sit still. Push the headline around, it always finds its way home.
A type foundry hero built on the text21 particle type component: the headline is drawn as thousands of particles sampled from its own font and layout, springing into the letters, scattering and swirling away from the cursor, lighting up in the primary color while moving and shimmering at rest, with a slow ghost pointer keeping touch screens alive. A short eyebrow, a description, a Turn Arrow block button and an underline link sit around it; the real text stays in the h1, colors follow the theme, it pauses offscreen and settles into still letters for reduced motion.
A full-height hero whose headline is drawn by text21 as thousands of Canvas 2D particles that fly into the letters, scatter and swirl away from the cursor and shimmer at rest, with an eyebrow above and an intro, a Turn Arrow block button and an underline link rising in below.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/hero203?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero203?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero203.tsx plus the text21 particle type, the button24 Turn Arrow button and the button2 underline link it uses.
The installed file exports hero203Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero203, hero203Demo } from "@/components/beste/block/hero203";
export default function Page() {
return <Hero203 {...hero203Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero203 } from "@/components/beste/block/hero203";
export default function Page() {
return (
<Hero203
eyebrow="Halden Type Foundry"
heading="Every letter, loose."
description="Drift is a variable grotesk drawn in 9 weights and cut for screens that never sit still."
buttons={[
{ label: "Try the specimen", href: "/specimen" },
{ label: "License Drift", href: "/license" },
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Muted line at the top of the section |
heading | string | – | Headline drawn as particles by Text21; the real text stays in the h1 |
description | string | – | Intro at the lower left |
buttons | ActionButton[] | [] | The first renders as a Turn Arrow block button (Button24), the rest as underline links (Button2) |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
};Text21 with its defaults: particles take currentColor at rest and var(--primary) while moving, react within 160px of the cursor, and a slow invisible pointer keeps them moving on touch screens.h1 and is made transparent only once the particles are ready, so screen readers, search and the first paint all get the words; the canvas is aria-hidden.20vw, 14vw from md and caps at 13rem from xl.