docs / patterns / hero-split

HeroSplit

the landing hero: copy on one side, a product visual on the other. every part but the title is optional, so it collapses to a headline and a button.

intensity · structuresrsc · server

provenance

shaped from sisu-plus

layer

core / patterns

intensity

structures · organizes a region, stays out of the content

composition

the first section of a landing page, onceactions take Buttons, proof takes an AvatarGroup, badge takes an Announcementnever nested inside a Card or another herothe background slot is not a place for content. it sits under a scrim

a11y

the title is a real heading, level set by headingLevel · the scrim is aria-hidden and the background layer drops pointer eventsjest-axe
live demo · try it out

Your whole degree, in one place.

Four registries reconciled into one planner. Nothing to configure.

+1
2,400 active users
product shot
customize
titlethe headline
titleAccentsecond phrase, carries the accent color
accentColorkeyed to the product, defaults to accent-alt
bodythe lede
notesmall print under the copy
badgepill above the title
actionsthe call to action row
proofan avatar group as social proof
visualthe product shot beside the copy
usagecopy
import { HeroSplit } from "@usva-ui/react/patterns/hero-split";
import { MockupShowcase } from "@usva-ui/react/patterns/mockup-showcase";
import { Avatar, AvatarGroup } from "@usva-ui/react/primitives/avatar";
import { Badge } from "@usva-ui/react/primitives/badge";
import { Button } from "@usva-ui/react/primitives/button";

<HeroSplit
  title="Your whole degree,"
  titleAccent="in one place."
  body="Four registries reconciled into one planner. Nothing to configure."
  actions={
    <>
      <Button>Add to Chrome</Button>
      <Button variant="onSurface">Source code</Button>
    </>
  }
  proof={
    <AvatarGroup max={3} tone="accent" label="2,400 active users">
      <Avatar alt="Mateusz Pasek" />
      <Avatar alt="Anna Korhonen" />
      <Avatar alt="Jussi Laine" />
    </AvatarGroup>
  }
  visual={<MockupShowcase>{/* screenshot */}</MockupShowcase>}
/>

props

proptypedefaultnotes
titleReactNodethe headline.
titleAccentReactNodesecond phrase of the title, carrying the accent color.
accentColorstringaccent-alt tokenany CSS color, keyed to the product.
headingLevel"h1" | "h2""h1"one h1 per page.
badgeReactNodepill above the title. an Announcement or a Badge.
bodyReactNodethe lede.
actionsReactNodethe call to action row. pass Buttons.
proofReactNodesocial proof under the actions. an AvatarGroup with a label does this.
noteReactNodesmall print under the copy.
visualReactNodethe product shot. beside the copy on wide containers, stacked below on narrow.
backgroundReactNodepainted behind everything, under a scrim built from the bg token. a slot, not a built-in atmosphere. no background, no scrim.

get it

bun add @usva-ui/reactcopy
usagecopy
import { HeroSplit } from "@usva-ui/react/patterns/hero-split";
import { MockupShowcase } from "@usva-ui/react/patterns/mockup-showcase";
import { Button } from "@usva-ui/react/primitives/button";

<HeroSplit
  title="Your whole degree,"
  titleAccent="in one place."
  body="Four registries reconciled into one planner."
  actions={<Button>Add to Chrome</Button>}
  visual={<MockupShowcase>{/* screenshot */}</MockupShowcase>}
/>