A festival of letterforms
A graphic design festival for people who still measure in picas. Three days of posters, talks and ink on the walls of an old print hall.
A Swiss poster hero on a faint twelve-column grid: a heavy rule with an eyebrow, a giant text20 headline whose letters drop in one by one and spring away from the cursor with a slight stretch, an intro beside a Turn Arrow block button, and a marquee1 band of words that speeds up and flips direction with scroll velocity.
A poster hero on a faint twelve-column grid where a giant headline drops in letter by letter and springs away from the cursor through text20, over an intro, a Turn Arrow block button and a full-width word band that speeds up and turns with the scroll through marquee1.
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/hero199?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/hero199?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/hero199.tsx plus the text20 repel letters, the button24 Turn Arrow button and the marquee1 velocity band it uses.
The installed file exports hero199Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.
import { Hero199, hero199Demo } from "@/components/beste/block/hero199";
export default function Page() {
return <Hero199 {...hero199Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Hero199 } from "@/components/beste/block/hero199";
export default function Page() {
return (
<Hero199
eyebrow="A festival of letterforms"
heading="Loud type, strict grid."
description="Three days of posters, talks and ink on the walls of an old print hall."
button={{ label: "Get a festival pass", href: "/tickets" }}
band={["Posters", "Talks", "Workshops", "Night print"]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Muted line under a heavy 2px rule at the top |
heading | string | – | Giant headline, rendered as the page h1 through Text20 |
description | string | – | Intro in the left half of the grid |
button | ActionButton | – | Turn Arrow block button (Button24) at the right of the intro row |
band | string[] | [] | Words carried by the Marquee1 band at the foot of the section |
className | string | – | Extra classes for the outer <section> |
type ActionButton = {
label: string;
href: string;
};Text20 with its defaults: letters drop in one by one on mount, then lean, stretch and spring back when the cursor comes within 240px. With reduced motion the entrance and the repel are both off.Text20 sets the full heading as the aria-label on the h1 and hides the per-letter spans from screen readers.Marquee1 with its defaults: the accent tone, diamond separators and followScroll on, so it speeds up with scroll velocity and flips to run the way the page scrolls. It stops when offscreen and stands still for reduced motion.md, drawn with border-foreground/[0.06] so it follows the theme.17vw, then 12vw from md, and caps at 11rem from xl.band has items.