caliper uidocs

Marketing sections

Block

Hero, feature and pricing sections for a landing page.

Installs components/ui/marketing-sections.tsxDepends on @radix-ui/react-slot, lucide-reactMotion shared motion tokens
pnpm dlx shadcn@latest add https://caliperui.site/r/marketing-sections.json

Announcement

Version 3 is here, with a new motion system.

See what is new

Navbar

Northwind

Hero, split

New: usage billing

Ship interfaces people trust

A component library where accessibility, motion and performance are part of every piece.

Hero, centered

Now in public beta

Calm software for busy teams

Fewer clicks, clearer screens and a keyboard shortcut for everything.

No card needed. Free for teams up to five.

Logo cloud

Trusted by teams at

  • Brightlabs
  • Harbour
  • Atlas
  • Quill
  • Nimbus
  • Orbit

Social proof

4.8

from 1,200 reviews

“The calmest tool we use.”

Features, grid

Everything a product team needs, nothing it does not

  • Fast

    Windowed lists and lazy canvases keep large data smooth.

  • Secure

    Roles, audit trails and single sign-on built in.

  • Themeable

    Tokens drive light, dark and your brand.

  • Keyboard first

    Every control and shortcut works without a mouse.

  • Global

    Time zones, locales and right-to-left layouts.

  • Motion

    Animation that explains change, then steps back.

Features, rows

See everything in one place

A single dashboard for plans, usage and people.

Move faster with shortcuts

Search any setting or action from the keyboard.

Content

Our approach

Design with the details in mind

We start with the states people forget: empty, loading, error and offline.

Then we make sure each one is calm, clear and reachable from the keyboard.

How it works

Up and running in three steps

  1. 1

    Copy the components

    Add only what you use to your project.

  2. 2

    Set your tokens

    Change colours, radius and type once.

  3. 3

    Ship

    Build, test and release with confidence.

Use cases

Plan, build and release in one flow

Roadmaps, boards and release checklists share a language.

  • Release readiness checks
  • Approvals with a paper trail
  • Board and list views

Pricing

  • Starter

    For trying things out.

    $0 forever

    • Up to 3 projects
    • Community support
    • Basic themes
  • Team

    Most chosen

    For teams that ship together.

    $24 per seat / month

    • Unlimited projects
    • Single sign-on
    • 90 days of history
    • Priority support
  • Enterprise

    For security and scale.

    Custom

    • Dedicated region
    • Audit log export
    • Custom roles
    • Named contact

Comparison

Why teams switch

Northwind

  • Accessible by default
  • Keyboard everywhere
  • One calm design language
  • You own the code

A typical kit

  • Accessibility as an add-on
  • Mouse-first menus
  • Mixed visual styles
  • Locked-in packages

Trust

Security you can check

  • SOC 2 Type II

    Audited yearly

  • GDPR

    EU data region

  • SSO and SCIM

    Okta, Entra, Google

  • 99.98% uptime

    Last 90 days

Stats

12,400+
teams
99.98%
uptime
38
countries
4.8
average rating

Testimonials

Loved by people who ship

  • We moved the whole team in an afternoon.
    Maya ChenPlatform lead
  • The keyboard support alone was worth switching.
    Ravi PatelProduct manager
  • Finally charts that explain themselves.
    Noor HaddadDesigner

Gallery

What we offer

What we offer

  • Components

    Hundreds of pieces that fit together.

  • Design system

    Tokens, motion and guidance.

  • Support

    Answers from the people who built it.

  • Templates

    Full pages to start from.

FAQ

Questions, answered

  • Yes. Copy the components you need and import them like any other file.

  • Everything reads a small set of CSS variables you can change.

  • Accessibility is a release requirement, with keyboard and reduced-motion support throughout.

Contact

Talk to a person

Newsletter

One useful email a month

Release notes, patterns and the occasional deep dive.

Call to action

Start building something calm

Free for small teams. Upgrade when you are ready.

Blog

Footer

When to use #

Use it for

  • Assembling a marketing page from tested sections.

Skip it when

  • The page is an application screen.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/marketing-sections.json

Adds its 8 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 #

example.tsx
import { BadgeCheck, Gauge, Globe, Layers, LifeBuoy, LockKeyhole, Mail, MessageCircle, Palette, Phone, ShieldCheck, Sparkles, Zap } from "lucide-react"
import { useState } from "react"
import { AnnouncementStrip, BlogFeatured, CenteredNavbar, ComparisonCards, ContactChannels, ContentSplit, CounterStats, CtaSplit, FaqColumns, FeatureGrid, FeatureRows, GalleryMosaic, HeroCentered, HeroSplit, HowItWorks, LogoCloud, MegaFooter, NewsletterCard, OfferList, PricingCards, SocialProof, TestimonialCards, TrustBadges, UseCaseTabs } from "@/components/ui/marketing-sections"
import { Button } from "@/components/ui/button"

const shot = (n: number, label: string) => (
  <div className="grid w-full max-w-sm gap-2" aria-hidden="true"><p className="text-xs uppercase tracking-wide text-muted-foreground">{label}</p>{[0.9, 0.62, 0.78].map((w, i) => <span key={i} className="block h-3 rounded-full" style={{ width: `${w * 100}%`, background: `color-mix(in srgb, var(--chart-${n}) ${70 - i * 16}%, var(--background))` }} />)}<span className="mt-1 block h-20 rounded-lg" style={{ background: `color-mix(in srgb, var(--chart-${n}) 24%, var(--background))` }} /></div>
);

const brand = <span className="flex items-center gap-2 text-base font-semibold"><Layers aria-hidden="true" className="size-5" />Northwind</span>;

const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));

const Block = ({ name, children }: { name: string; children: React.ReactNode }) => <section className="grid min-w-0 gap-1 rounded-xl border border-dashed border-border"><p className="px-4 pt-3 text-xs font-medium uppercase tracking-wide text-muted-foreground">{name}</p>{children}</section>;

export function MarketingSectionsDemo() {
  const [bar, setBar] = useState(true);
  return (
    <div className="grid gap-8">
      {bar && <Block name="Announcement"><AnnouncementStrip action={<a href="#" className="font-medium underline underline-offset-4">See what is new</a>} onDismiss={() => setBar(false)}>Version 3 is here, with a new motion system.</AnnouncementStrip></Block>}
      <Block name="Navbar"><CenteredNavbar brand={brand} links={[{ label: "Product", href: "#" }, { label: "Pricing", href: "#" }, { label: "Docs", href: "#" }, { label: "Blog", href: "#" }]} actions={<><Button variant="ghost" size="sm">Sign in</Button><Button size="sm">Get started</Button></>} /></Block>
      <Block name="Hero, split"><HeroSplit eyebrow="New: usage billing" title="Ship interfaces people trust" description="A component library where accessibility, motion and performance are part of every piece." actions={<><Button size="lg">Start free</Button><Button size="lg" variant="secondary">Read the docs</Button></>} media={shot(1, "Dashboard")} /></Block>
      <Block name="Hero, centered"><HeroCentered badge={<span className="rounded-full border border-border px-3 py-1 text-xs text-muted-foreground">Now in public beta</span>} title="Calm software for busy teams" description="Fewer clicks, clearer screens and a keyboard shortcut for everything." actions={<><Button size="lg">Try it free</Button><Button size="lg" variant="ghost">Book a demo</Button></>} footnote="No card needed. Free for teams up to five." /></Block>
      <Block name="Logo cloud"><LogoCloud title="Trusted by teams at" logos={["Brightlabs", "Harbour", "Atlas", "Quill", "Nimbus", "Orbit"].map((n) => ({ id: n, name: n }))} /></Block>
      <Block name="Social proof"><SocialProof rating={4.8} count="1,200 reviews" people={["Maya Chen", "Ravi Patel", "Noor Haddad", "Kofi Mensah", "Lena Fischer"]} quote="The calmest tool we use." /></Block>
      <Block name="Features, grid"><FeatureGrid title="Everything a product team needs, nothing it does not" features={[{ id: "a", icon: <Gauge />, title: "Fast", body: "Windowed lists and lazy canvases keep large data smooth." }, { id: "b", icon: <ShieldCheck />, title: "Secure", body: "Roles, audit trails and single sign-on built in." }, { id: "c", icon: <Palette />, title: "Themeable", body: "Tokens drive light, dark and your brand." }, { id: "d", icon: <Zap />, title: "Keyboard first", body: "Every control and shortcut works without a mouse." }, { id: "e", icon: <Globe />, title: "Global", body: "Time zones, locales and right-to-left layouts." }, { id: "f", icon: <Sparkles />, title: "Motion", body: "Animation that explains change, then steps back." }]} /></Block>
      <Block name="Features, rows"><FeatureRows features={[{ id: "r1", title: "See everything in one place", body: "A single dashboard for plans, usage and people.", media: shot(2, "Overview") }, { id: "r2", title: "Move faster with shortcuts", body: "Search any setting or action from the keyboard.", media: shot(3, "Command") }]} /></Block>
      <Block name="Content"><ContentSplit eyebrow="Our approach" title="Design with the details in mind" media={shot(4, "Details")}><p>We start with the states people forget: empty, loading, error and offline.</p><p>Then we make sure each one is calm, clear and reachable from the keyboard.</p></ContentSplit></Block>
      <Block name="How it works"><HowItWorks title="Up and running in three steps" steps={[{ id: "1", title: "Copy the components", body: "Add only what you use to your project." }, { id: "2", title: "Set your tokens", body: "Change colours, radius and type once." }, { id: "3", title: "Ship", body: "Build, test and release with confidence." }]} /></Block>
      <Block name="Use cases"><UseCaseTabs cases={[{ id: "p", label: "Product teams", title: "Plan, build and release in one flow", body: "Roadmaps, boards and release checklists share a language.", points: ["Release readiness checks", "Approvals with a paper trail", "Board and list views"], media: shot(1, "Board") }, { id: "s", label: "Support", title: "Answer faster with context", body: "See the customer, the plan and the history side by side.", points: ["Saved replies", "SLA timers", "Private notes"], media: shot(2, "Ticket") }, { id: "f", label: "Finance", title: "Bills that explain themselves", body: "Usage, tiers and totals shown line by line.", points: ["Usage forecasts", "Budget alerts", "Invoice editor"], media: shot(3, "Invoice") }]} /></Block>
      <Block name="Pricing"><PricingCards tiers={[{ id: "s", name: "Starter", price: "$0", period: "forever", description: "For trying things out.", cta: "Start free", features: ["Up to 3 projects", "Community support", "Basic themes"] }, { id: "t", name: "Team", price: "$24", period: "per seat / month", description: "For teams that ship together.", cta: "Start a trial", featured: true, features: ["Unlimited projects", "Single sign-on", "90 days of history", "Priority support"] }, { id: "e", name: "Enterprise", price: "Custom", description: "For security and scale.", cta: "Contact sales", features: ["Dedicated region", "Audit log export", "Custom roles", "Named contact"] }]} /></Block>
      <Block name="Comparison"><ComparisonCards title="Why teams switch" us={{ name: "Northwind", points: ["Accessible by default", "Keyboard everywhere", "One calm design language", "You own the code"] }} them={{ name: "A typical kit", points: ["Accessibility as an add-on", "Mouse-first menus", "Mixed visual styles", "Locked-in packages"] }} /></Block>
      <Block name="Trust"><TrustBadges title="Security you can check" badges={[{ id: "a", label: "SOC 2 Type II", detail: "Audited yearly", icon: <BadgeCheck /> }, { id: "b", label: "GDPR", detail: "EU data region", icon: <Globe /> }, { id: "c", label: "SSO and SCIM", detail: "Okta, Entra, Google", icon: <LockKeyhole /> }, { id: "d", label: "99.98% uptime", detail: "Last 90 days", icon: <ShieldCheck /> }]} /></Block>
      <Block name="Stats"><CounterStats stats={[{ id: "a", value: 12400, label: "teams", suffix: "+" }, { id: "b", value: 99.98, label: "uptime", suffix: "%" }, { id: "c", value: 38, label: "countries" }, { id: "d", value: 4.8, label: "average rating" }]} /></Block>
      <Block name="Testimonials"><TestimonialCards title="Loved by people who ship" items={[{ id: "1", quote: "We moved the whole team in an afternoon.", name: "Maya Chen", role: "Platform lead" }, { id: "2", quote: "The keyboard support alone was worth switching.", name: "Ravi Patel", role: "Product manager" }, { id: "3", quote: "Finally charts that explain themselves.", name: "Noor Haddad", role: "Designer" }]} /></Block>
      <Block name="Gallery"><GalleryMosaic items={[{ id: "1", label: "Dashboard", size: "wide", node: shot(1, "Dashboard") }, { id: "2", label: "Board", node: shot(2, "Board") }, { id: "3", label: "Editor", size: "tall", node: shot(3, "Editor") }, { id: "4", label: "Charts", node: shot(4, "Charts") }, { id: "5", label: "Settings", node: shot(5, "Settings") }]} /></Block>
      <Block name="What we offer"><OfferList title="What we offer" items={[{ id: "1", icon: <Layers />, title: "Components", body: "Hundreds of pieces that fit together." }, { id: "2", icon: <Palette />, title: "Design system", body: "Tokens, motion and guidance." }, { id: "3", icon: <LifeBuoy />, title: "Support", body: "Answers from the people who built it." }, { id: "4", icon: <Sparkles />, title: "Templates", body: "Full pages to start from." }]} /></Block>
      <Block name="FAQ"><FaqColumns title="Questions, answered" items={[{ id: "1", q: "Can I use it in an existing app?", a: "Yes. Copy the components you need and import them like any other file." }, { id: "2", q: "Does it work with my design tokens?", a: "Everything reads a small set of CSS variables you can change." }, { id: "3", q: "Is it accessible?", a: "Accessibility is a release requirement, with keyboard and reduced-motion support throughout." }]} /></Block>
      <Block name="Contact"><ContactChannels title="Talk to a person" channels={[{ id: "e", icon: <Mail />, label: "Email", detail: "We reply within a day.", action: "hello@northwind.co", href: "mailto:hello@northwind.co" }, { id: "p", icon: <Phone />, label: "Phone", detail: "Weekdays, 9 to 6 CET.", action: "+49 30 1234 5678", href: "tel:+493012345678" }, { id: "c", icon: <MessageCircle />, label: "Chat", detail: "Usually under 5 minutes.", action: "Start a chat", href: "#" }]} /></Block>
      <Block name="Newsletter"><NewsletterCard title="One useful email a month" description="Release notes, patterns and the occasional deep dive." onSubmit={async () => { await wait(700); }} /></Block>
      <Block name="Call to action"><CtaSplit title="Start building something calm" description="Free for small teams. Upgrade when you are ready." actions={<><Button size="lg" variant="secondary">Get started</Button><Button size="lg" variant="ghost" className="text-background hover:bg-background/15">Talk to sales</Button></>} media={shot(5, "Preview")} /></Block>
      <Block name="Blog"><BlogFeatured featured={{ id: "f", tag: "Product", date: "Oct 21", title: "How we made a dashboard that explains itself", excerpt: "Every chart gets a sentence and a table. Here is what we learned from shipping that rule.", author: "Maya Chen", media: shot(2, "Article") }} posts={[{ id: "1", tag: "Engineering", date: "Oct 14", title: "Virtualising 50,000 rows without losing the keyboard", author: "Lena Fischer" }, { id: "2", tag: "Design", date: "Oct 7", title: "Motion that explains, then gets out of the way", author: "Noor Haddad" }, { id: "3", tag: "Company", date: "Sep 29", title: "What our uptime page does and does not say", author: "Ravi Patel" }]} /></Block>
      <Block name="Footer"><MegaFooter brand={brand} blurb="Calm, accessible software for teams who ship." columns={[{ title: "Product", links: [{ label: "Features", href: "#" }, { label: "Pricing", href: "#" }, { label: "Changelog", href: "#" }] }, { title: "Company", links: [{ label: "About", href: "#" }, { label: "Careers", href: "#" }, { label: "Contact", href: "#" }] }, { title: "Resources", links: [{ label: "Docs", href: "#" }, { label: "Blog", href: "#" }, { label: "Status", href: "#" }] }, { title: "Legal", links: [{ label: "Privacy", href: "#" }, { label: "Terms", href: "#" }, { label: "Security", href: "#" }] }]} legal="© 2025 Northwind. All rights reserved." onSubscribe={async () => { await wait(500); }} /></Block>
    </div>
  );
}

API reference #

HeroSplit

component
PropTypeDefault
eyebrowstring—
title *ReactNode—
description *string—
actionsReactNode—
media *ReactNode—
classNamestring—

HeroCentered

component
PropTypeDefault
badgeReactNode—
title *ReactNode—
description *string—
actionsReactNode—
footnotestring—
classNamestring—

PricingCards

component
PropTypeDefault
tiers *readonly Tier[]—
classNamestring—

MegaFooter

component
PropTypeDefault
brand *ReactNode—
blurb *string—
columns *readonly { title: string; links: readonly { label: string; href: string; }[]; }[]—
legal *ReactNode—
onSubscribe((email: string) => Promise<void>)—
classNamestring—

FeatureGrid

component
PropTypeDefault
title *string—
features *readonly Feature[]—
classNamestring—

FeatureRows

component
PropTypeDefault
features *readonly Feature[]—
classNamestring—

ContentSplit

component
PropTypeDefault
eyebrowstring—
title *string—
children *ReactNode—
mediaReactNode—
flipboolean—
classNamestring—

BlogFeatured

component
PropTypeDefault
featured *FeaturedPost—
posts *readonly FeaturedPost[]—
classNamestring—

TrustBadges

component
PropTypeDefault
title *string—
badges *readonly { id: string; label: string; detail: string; icon?: ReactNode; }[]—
classNamestring—

AnnouncementStrip

component
PropTypeDefault
children *ReactNode—
actionReactNode—
onDismiss(() => void)—
classNamestring—

UseCaseTabs

component
PropTypeDefault
cases *readonly { id: string; label: string; title: string; body: string; points: readonly string[]; media?: ReactNode; }[]—
classNamestring—

HowItWorks

component
PropTypeDefault
title *string—
steps *readonly { id: string; title: string; body: string; }[]—
classNamestring—

LogoCloud

component
PropTypeDefault
title *string—
logos *readonly { id: string; name: string; node?: ReactNode; }[]—
classNamestring—

SocialProof

component
PropTypeDefault
rating *number—
count *string—
people *readonly string[]—
quotestring—
classNamestring—

CounterStats

component
PropTypeDefault
stats *readonly { id: string; value: number; label: string; prefix?: string | undefined; suffix?: string | undefined; }[]—
classNamestring—

TestimonialCards

component
PropTypeDefault
titlestring—
items *readonly { id: string; quote: string; name: string; role: string; }[]—
classNamestring—

GalleryMosaic

component
PropTypeDefault
items *readonly { id: string; node: ReactNode; label: string; size?: "wide" | "tall" | undefined; }[]—
classNamestring—

CenteredNavbar

component
PropTypeDefault
brand *ReactNode—
links *readonly { label: string; href: string; }[]—
actionsReactNode—
classNamestring—

NewsletterCard

component
PropTypeDefault
title *string—
description *string—
onSubmit *(email: string) => Promise<void>—
classNamestring—

ContactChannels

component
PropTypeDefault
title *string—
channels *readonly { id: string; label: string; detail: string; action: string; href: string; icon?: ReactNode; }[]—
classNamestring—

ComparisonCards

component
PropTypeDefault
title *string—
us *{ name: string; points: readonly string[]; }—
them *{ name: string; points: readonly string[]; }—
classNamestring—

FaqColumns

component
PropTypeDefault
title *string—
items *readonly { id: string; q: string; a: string; }[]—
classNamestring—

CtaSplit

component
PropTypeDefault
title *string—
description *string—
actions *ReactNode—
mediaReactNode—
classNamestring—

OfferList

component
PropTypeDefault
title *string—
items *readonly { id: string; icon?: ReactNode; title: string; body: string; }[]—
classNamestring—

Accessibility #

It exposes status, region, tablist, tab, tabpanel, img and alert semantics, with aria-hidden, aria-label, aria-selected, aria-controls, aria-labelledby and aria-expanded kept in step with state. Changes that matter are announced through a live region.

KeyBehaviour
→Moves to the next item or value.
←Moves to the previous item or value.

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.