Hero section
BlockThe top of a landing page: eyebrow, title, copy, actions and proof.
pnpm dlx shadcn@latest add https://caliperui.site/r/hero-section.jsonInterface parts you own, with the details done
Install readable components, edit them freely, and ship screens that feel finished: keyboard first, calm motion, real states.
Free to start. No card needed.
When to use #
Use it for
- A page needs a clear promise and one main action.
- Adding media or logos beneath the copy.
Skip it when
- Inside the product; use a page header.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/hero-section.json
Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
import { ArrowRight } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { HeroSection } from "@/components/ui/hero-section" export function HeroSectionDemo() { return ( <HeroSection animated eyebrow={ <a href="#changelog" className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-3 py-1 text-xs no-underline outline-none hover:bg-muted focus-visible:outline-2 focus-visible:outline-ring"> <Badge>New</Badge> Agents, tables and threads <ArrowRight aria-hidden="true" className="size-3" /> </a> } title="Interface parts you own, with the details done" description="Install readable components, edit them freely, and ship screens that feel finished: keyboard first, calm motion, real states." actions={ <> <Button size="lg">Get started</Button> <Button size="lg" variant="secondary">Browse components</Button> </> } note="Free to start. No card needed." media={ <div className="overflow-hidden rounded-overlay border border-border bg-background"> <div className="flex items-center gap-1.5 border-b border-border px-3 py-2" aria-hidden="true"> <span className="size-2.5 rounded-full bg-muted-foreground/40" /> <span className="size-2.5 rounded-full bg-muted-foreground/40" /> <span className="size-2.5 rounded-full bg-muted-foreground/40" /> </div> <div className="grid gap-3 p-5 sm:grid-cols-3" aria-hidden="true"> {[72, 48, 88].map((w, i) => ( <div key={i} className="grid gap-2 rounded-surface bg-surface p-4"> <span className="h-2 w-1/3 rounded-full bg-foreground/15" /> <span className="h-6 rounded-md bg-foreground/10" style={{ width: `${w}%` }} /> <span className="h-2 w-2/3 rounded-full bg-foreground/10" /> </div> ))} </div> </div> } proof="Trusted by product teams at studios, startups and agencies." /> ); }
API reference #
HeroSection
component
Accessibility #
It is built on native elements, so roles and focus come from the browser.
No custom key handling; Tab and the native activation keys do the work.
Motion #
Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.