Hero

Pro

A centered marketing hero section. Named parts you assemble: an announcement eyebrow, a balanced headline, a subtitle, a CTA row, a check-circle feature list and an integrated social-proof row.

Just shippedKoala UI for React is finally here

A Design System built for AI‑Powered Products

A Design System for builders of AI assistants, copilots and intelligent tools, ship MVPs fast.

  • Light/Dark/Moonlight themes at 1 click
  • +3,200 Components
  • New updates every month
  • Consistent responsive
LCKPDB
+620 Designers have joined already
5.0 Ratings

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Activate your Pro license (once per machine)npx koalaui-cli@latest login <key># Add this component (its dependencies come along)npx koalaui-cli@latest add hero

Usage#

This example is part of Koala UI Pro

The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.

Have a license? Unlock it here

Anatomy#

import {  Hero,  HeroContent,  HeroColumn,  HeroTitle,  HeroHighlight,  HeroSubtitle,  HeroActions,  HeroFeatures,  HeroFeature,  HeroSocialProof,  HeroRating,  HeroMedia,  HeroBackground,  HeroCursors,  HeroCursor,  HeroScatter,  HeroScatterTile,  HeroStage,  HeroStageMedia,  HeroStageTitle,  HeroStageCard,  HeroStageReveal,  HeroSpread,  HeroSpreadMedia,  HeroSpreadPanel,  HeroSpreadIndex,  HeroStatement,  HeroSignoff,  HeroMosaic,  HeroFrame,} from "@/components/ui/hero"<Hero>  <HeroBackground />  <HeroScatter>    <HeroScatterTile />  </HeroScatter>  <HeroCursors>    <HeroCursor />  </HeroCursors>  <HeroContent>    <HeroColumn>      <HeroTitle>        <HeroHighlight />      </HeroTitle>      <HeroSubtitle />      <HeroActions />      <HeroFeatures>        <HeroFeature />      </HeroFeatures>      <HeroSocialProof>        <HeroRating />      </HeroSocialProof>    </HeroColumn>    <HeroMedia />  </HeroContent></Hero>{/* Alternative bodies, each in place of HeroContent */}<HeroStage>  <HeroStageMedia>    <HeroStageTitle />  </HeroStageMedia>  <HeroStageCard />  <HeroStageReveal /></HeroStage><HeroSpread>  <HeroSpreadMedia />  <HeroSpreadPanel>    <HeroSpreadIndex />    <HeroColumn />    <HeroColumn />  </HeroSpreadPanel></HeroSpread><HeroContent>  <HeroMosaic>    <HeroFrame />  </HeroMosaic>  <HeroStatement />  <HeroSignoff /></HeroContent>

Minimal#

Drop the features and social-proof rows for a lean hero: just the eyebrow, title, subtitle, and CTAs. Override the vertical rhythm on HeroContent when you want it tighter.

New: Koala UI for React

Build polished products, faster

A production-ready component library you can install with one command and own forever.

Display title#

size on HeroTitle sets the headline's scale. The default "lg" peaks at 60px, level with a SectionHeader size="lg"; "xl" is the display cut for the page's one big statement, peaking at 72px. The tracking stays tight: DM Sans follows its optical-size axis, so at display sizes it already sets in its tighter cut. Widen the column with max-w-5xl on HeroContent so a display headline keeps two lines, and give the rating size="md" stars so the proof row holds its own under the bigger type.

Just shippedKoala UI for React is finally here

A Design System built for AI‑Powered Products

A Design System for builders of AI assistants, copilots and intelligent tools, ship MVPs fast.

LMCGKSPKDKBP
5.0 Ratings

Rotating highlight#

Pass rotate a list of phrases to HeroHighlight and the wash becomes a rotating zone: the words inside swap, each entering with a per-character stagger while the previous one clears, the wash hugs each word (tweening its width as the phrase changes), and each phrase takes the next color in the palette (semantic DS roles, so it tracks every theme), the tint crossfading as it swaps. Lead every phrase with the same word so the left edge stays anchored against the copy beside it and only the right edge resizes. Give the title a touch more line-height (the demo uses leading-[1.2]) so the wash always clears the line above it. It holds each phrase for interval ms (default 2600) and honors prefers-reduced-motion by holding the first phrase with no cascade.

Koala UI v1.0 is here

Bring your product into

The highlight wash hugs each word, resizing as it rotates, paints each phrase in its own color, and the letters arrive with a per-character stagger, so the headline stays alive on its own.

Cursors#

Add a HeroCursors layer and place HeroCursors in it for the feel of a live, shared design file. Each cursor wanders its own slow loop, pauses twice, and clicks at each pause: the arrow presses and a soft ripple leaves the tip. Give every cursor a different duration (seconds per loop, default 16) and phase (0 to 1) so they never move in step. color takes a semantic role (brand, purple, teal, pink, orange, success), so the fills follow every theme, and facing points the arrow left or right; the name tag always hangs on the side away from the point. Place each cursor's tip with className, and resize its loop with [--cursor-x:…] / [--cursor-y:…] (a negative x mirrors it).

Pass labels (an array of names) instead of children and the name tag rolls to the next one on every click, twice a loop: the old name lifts out, the new one rises in, and the pill eases to its width, the same AnimatedLabel roll every changing label in Koala uses. The swap is timed off the cursor's own loop, so it always lands as the arrow presses, and it stops whenever the cursor is hidden.

The layer is decoration only. It is hidden from assistive tech, lets every click through to the copy underneath, and shows its cursors only when the hero itself is at least 64rem wide (a container query, so it reads the hero's width, not the window's), which keeps them in the gutters and off the headline on smaller frames. When your cursors roam space the copy never reaches (the bands above and below it, as in this demo), reveal them sooner with className="@2xl:block" (a 42rem hero). Under prefers-reduced-motion they hold still where you placed them, with no ripple.

Built together

Where your whole team designs in one place

Clients, developers and designers working in the same file, each cursor on its own path.

Poster wall#

When the product itself is a wall of covers (events, classes, listings, releases), open on that content instead of a screenshot of it. A HeroScatter layer fills the band with tilted HeroScatterTile prints and the copy stands in the clearing at its centre. Each tile takes a size (sm / md / lg, square, stepping up twice as the hero widens), a depth (far sits it smaller and lighter, further back), a tilt in degrees, and a delay, so the wall assembles card by card on mount. Place each one with className; a negative offset (-left-4) lets the band crop it, which is what makes the wall read as bigger than the page.

Give the copy a taller pt / pb than usual: that clearing is what keeps the top and bottom cards off the words where there are no gutters to put them in. The layer is a size container, so hold the rest back until the hero has earned the room (hidden @5xl:block for the sides of a 48rem copy column). Like the cursors it is decoration only: hidden from assistive tech, never in the way of a click, and still under prefers-reduced-motion. The copy on top of it stays the house stack, and the headline goes plain: the wall is already the colour on this band, and a HeroHighlight wash under a 72px line reads as a slab rather than an accent.

Free to host

Host the kind of night people talk about

Supper clubs, workshops, launch parties, a five-a-side game: build the page, send the invite, and keep every RSVP in one place.

Feature columns#

HeroFeatures has a second shape. Set layout="columns" and the inline check row becomes three capability columns, each a bare mark in full ink over a title and a sentence: pass icon and title to every HeroFeature inside and the sentence stays as its children. Reach for it when the three claims each deserve a sentence rather than three words, and the page has no room for a separate feature section above the fold.

Nothing is drawn between the columns: no rule, no padding, no surface, so the gutter carries the separation and stays wide enough to do it. It is a grid, not a wrapping row, and every column subgrids onto the same three tracks, so a title that wraps to two lines pushes all three sentences down together instead of stranding its neighbours half a line high. Below the sm breakpoint the tracks collapse and the columns stack. The row follows the hero it sits in: centered under a centered column, flush-left in a split, and white over background media.

Design to launch

Design, build and launch in one place

Eighty-nine components, four themes and whole page sections, wired together so the site you sketch on Monday is live on Friday.

  • Make it yours

    Four themes and a radius knob, so the kit wears your brand before you write a line.

  • Build from finished parts

    Whole page sections, not just buttons: paste a hero, a pricing table, a footer.

  • Ship the same day

    You own the source. Drop it in your repo and launch without waiting on a handoff.

A careers page and an FAQ page built with Koala UI, side by side in two browser windows

Split layout#

Set layout="split" on Hero to turn the content into a two-column grid: a HeroColumn of copy beside a HeroMedia visual (an image, screenshot, or logo wall). It folds back to a single stacked column below the lg breakpoint. The same parts read the layout from context, so the only change is the prop.

Now in public beta

Analytics your whole team actually uses

Real-time dashboards with no setup. Connect a source and watch the numbers land in seconds, on every device.

APTM
Loved by 2,000+ teams

Background media#

Set layout="background" and add a HeroBackground to turn the hero into a full-bleed band: the media covers the section, a gradient scrim lays over it, the copy flips to white, and the eyebrow goes glassy, all from the one prop. Drop a plain <img> in for a photo, or an autoPlay muted loop playsInline <video> for ambient motion (muted autoplay is the only kind browsers allow unprompted). Give the video a poster so the band never flashes empty, and a still <img className="hidden motion-reduce:block"> fallback so it holds a frame under prefers-reduced-motion.

Now in private beta

Support that never sleeps

AI agents pick up every call, answer in seconds, and hand off to your team only when it matters.

Series A: $61M to scale support

AI that talks like a human. Handles millions of calls.

AI agents for enterprise support.

ApexHelioDewnCobaltBlossom

Scroll stage#

HeroStage is the hero that plays itself as the reader scrolls: one photograph opens full-bleed under a display line, contracts into a centred card, and a collage assembles around it while the copy rises underneath. Several things move at once rather than one: the frame contracts, the picture inside it pushes in on its own slower beat (so the shot gains depth instead of just getting smaller), the display line grows past the frame and defocuses as the camera goes through it, and each collage piece flies in from its own edge, leaning, and settles level. Once landed, the pictures keep a slow drift inside their frames, each on its own clock, so the composition breathes instead of freezing when the reader stops. All of it is scrubbed by the scroll position through a single CSS view timeline, so there is no animation library, no scroll listener and no requestAnimationFrame loop anywhere in it: it runs backwards when the reader scrolls back up, and costs nothing off screen. Compose it in place of HeroContent. Every part is droppable, so a stage holding nothing but a HeroStageMedia is a picture that contracts.

It spends three viewports of scrolling on a single statement, so it is a page's one cinematic moment, not a section to reach for twice. Browsers with no scroll-driven animations, and readers who asked for reduced motion, get a single viewport holding the last frame: the picture at its card size, the collage assembled around it, and the eyebrow, lede and CTAs where they land. Only the display word is missing there, since a word cut to fill a screen cannot sit inside a card, so put an ordinary HeroTitle in the closing HeroStageReveal when the section needs a headline visible at rest. See the scroll stage section for the finished slab.

Parallax cover#

layout="cover" is the editorial opener: one picture or clip takes the whole viewport (100svh, so a phone's shrinking browser chrome can never cut the words off) and the copy stands along its bottom edge, the headline in one corner and the paragraph in the other. Where layout="background" centres a copy column in the middle of the band and treats the media as a backdrop for it, here the media is the statement and the words are a caption laid along the foot of it, so the frame is never covered. Set the headline to size="2xl", the 96px poster cut, and keep it to two or three words.

It does not stay full bleed. As the reader scrolls, the frame pulls in to the page's own container (90rem, the max-w-8xl every other section sits in) and rounds its corners, so the opening picture hands the page back to its grid instead of ending at a hard seam. One registered number, --hero-cover-t, animates on the band and the frame's width, its corner and the caption's padding are calc()s reading it, so they cannot drift out of step: the caption steps in by exactly what the frame pulls in by and the words hold the same distance from the picture's edge from the first frame to the last, at every width. Retune the landing with [--hero-cover-gutter:…], [--hero-cover-max:…] and [--hero-cover-radius:…], and when it runs with [--hero-cover-contract-start:…] / -end (a hero opens at the top of the page, which is already halfway through its own cover range, so the beat starts at 50% and finishes half a viewport of scrolling later).

The parallax is one prop: <HeroBackground parallax>. The media travels slower than the band it fills while the caption over it travels a little faster, so the two planes separate and the band reads as a window rather than a picture glued to the page. It is scrubbed by the scroll position through a CSS view timeline, the same engine the scroll stage runs on, so there is no animation library (parallax is the effect people install GSAP and Lenis for), no scroll listener and no requestAnimationFrame loop: it runs on the compositor, off the main thread, goes backwards when the reader scrolls back up, and costs nothing off screen. The media is held a quarter larger than its frame for the whole travel, which is the slack the drift moves within, so give it a picture with room around its subject. Retune with [--hero-parallax-travel:…] and [--hero-parallax-zoom:…] on the hero, keeping travel at or under (zoom - 1) / 2 or the frame will show its ground at the ends of the drift.

Browsers with no scroll-driven animations, and readers who asked for reduced motion, get the same hero full bleed and still, with the media sitting level in its frame: a parallax has a neutral frame, and the neutral frame is a finished, full-bleed cover. The drift also works under layout="background", which declares the same timeline. See the parallax cover section for the finished slab.

API reference#

Hero

The full-bleed <section> that provides the styling context; every part reads its layout. Forwards all native <section> props; every part accepts className, merged last.

PropTypeDefaultDescription
layout"centered" | "split" | "background" | "cover""centered"One centered column; copy beside a HeroMedia; light copy centered over a HeroBackground; or a full-viewport picture with the copy along its bottom edge.
CSS variableDescription
--hero-parallax-travelHow far a parallax background drifts. Keep it at or under (zoom - 1) / 2.
--hero-parallax-zoomHow much larger than its frame a parallax background is held, the slack the drift moves within.
--hero-cover-guttercover: what the contracted frame leaves at the page edge.
--hero-cover-maxcover: the container the frame lands in (the site's 8xl by default).
--hero-cover-radiuscover: the corner the frame rounds to (radius-3xl by default).
--hero-cover-padcover: the caption's padding inside the frame, before the gutter is added.
--hero-cover-contract-startcover: where in the scroll the contraction starts (with -end).

HeroContent

The max-width content column: the stacked column itself when centered, the two-column grid holding a HeroColumn and a HeroMedia when split. Forwards all native <div> props.

HeroColumn

Groups the copy stack in a split hero or a spread panel. Forwards all native <div> props.

HeroTitle

The balanced <h1>; the pill above it is the standalone Announcement (variant="glass" over media), not a Hero part. Forwards all native <h1> props.

PropTypeDefaultDescription
size"lg" | "xl" | "2xl""lg"Peaks at 60px; xl is the 72px display cut; 2xl the 96px poster cut for the foot of a cover.

HeroHighlight

A keyword marker inside a title or statement: a soft ink wash, the only way Koala marks a word in a headline (no gradient text). Forwards all native <span> props.

PropTypeDefaultDescription
rotatestring[]-Cycle a fixed zone through these phrases, each entering with a per-character stagger and its own color. Needs two or more; holds the first under reduced motion.
intervalnumber2600Milliseconds each phrase holds before the next swaps in.

HeroSubtitle

The muted lead paragraph. Forwards all native <p> props.

HeroActions

The CTA row: drop Buttons in, no size needed. Forwards all native <div> props.

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""xl"Control height imposed on the children; an explicit one still wins. Pass lg beside an inline signup Input so field and button match.
Data attributeDescription
data-control-sizeThe imposed control size.

HeroFeatures

The feature list, a <ul>. Forwards all native <ul> props.

PropTypeDefaultDescription
layout"inline" | "columns""inline"A wrapping check-circle checklist, or three hairline-divided capability columns whose items take icon and title.
balancebooleanfalseCaps the row at a 36rem measure so items wrap into even rows (2 + 2, not 3 + 1). Ignored by columns.
Data attributeDescription
data-layout"inline" or "columns".

HeroFeature

One item, an <li>: inline it draws its own green check-circle before the label; in columns, given a title, it becomes a column with children as the sentence. Forwards all native <li> props.

PropTypeDefaultDescription
iconReact.ReactNode-columns only: the bare mark in full ink, sized to 20px. Give every item in the row one, or none.
titleReact.ReactNode-columns only: the one-line claim. Without it the item stays an inline check row.

HeroSocialProof

The proof row: an AvatarGroup beside a HeroRating. Forwards all native <div> props.

HeroRating

A read-only Rating with its label ("5.0 Ratings") as children. Forwards all native <div> props.

PropTypeDefaultDescription
valuenumber5Filled stars.
maxnumber5Total stars.
size"sm" | "md" | "lg""sm"Star size: 16px beside a one-line label, md (20px) beside a larger avatar stack.

HeroMedia

The visual region: the second column of a split hero, or below the copy when centered. Drop a screenshot, product window or logo wall in; forwards all native <div> props.

HeroBackground

The full-bleed media layer for background and cover: stretches a child <img> or <video> to cover the band under a gradient scrim. Forwards all native <div> props.

PropTypeDefaultDescription
parallaxbooleanfalseDrift the media against the page on scroll through a CSS view timeline; still under reduced motion. Give it a picture with room around its subject.
Data attributeDescription
data-parallaxPresent when parallax is on.

HeroCursors

The decorative multiplayer-cursor layer: covers the hero, aria-hidden, lets clicks through, and shows its cursors once the hero is 64rem wide. Forwards all native <div> props.

HeroCursor

One wandering cursor, positioned by its tip via className (left-[12%] top-[20%]); children is the name tag. Holds still under reduced motion; forwards all native <div> props.

PropTypeDefaultDescription
color"brand" | "purple" | "teal" | "pink" | "orange" | "success""brand"The cursor and name-tag fill.
facing"left" | "right""left"Which way the arrow points; the label hangs on the other side.
durationnumber16Seconds per loop. Vary it per cursor.
phasenumber0Where in its loop it starts, 0 to 1, so siblings never move in step.
labelsreadonly string[]-Names the tag rolls through, one per click, in place of children.
Data attributeDescription
data-colorThe color value.
data-facing"left" or "right".
CSS variableDescription
--cursor-xHorizontal reach of the loop (28px by default); negative mirrors it.
--cursor-yVertical reach of the loop (20px by default).

HeroScatter

The poster-wall layer behind the copy: covers the hero, aria-hidden, never blocks a click, and is a size container. Forwards all native <div> props.

HeroScatterTile

One photo print in the wall, placed by className (left-[8%] top-16, hidden @5xl:block) around a plain <img> it sizes and crops. Forwards all native <div> props.

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"The square card size; each steps up as the hero widens.
depth"near" | "far""near"far steps the card back into the page behind the near ones.
tiltnumber0Degrees it leans, positive clockwise; keep the wall between about -12 and 12.
delaynumber0Milliseconds before it drifts in, so the wall assembles card by card.

HeroStage

The scroll stage, composed instead of HeroContent: a track taller than the viewport with one pinned screen, the only part that declares the timeline. Forwards all native <div> props.

CSS variableDescription
--hero-stage-trackTotal scroll length of the section (default 280svh).
--hero-stage-wWidth of the card the picture lands on.
--hero-stage-hHeight of the card the picture lands on.
--hero-stage-radiusThe landed card's corner.
--hero-stage-staggerScroll gap between stagger steps (4% of the pin by default).

HeroStageMedia

The frame that contracts from full-bleed to a card, covering a plain <img> or <video>; put HeroStageTitle inside it. Forwards all native <div> props.

PropTypeDefaultDescription
scrimbooleantrueA bottom-weighted gradient that carries the display word and leaves with it.

HeroStageTitle

The section's <h1> at poster scale, trimmed by the frame; two or three words. A plain string leaves character by character, with the heading keeping the text as its label. Forwards all native <h1> props.

CSS variableDescription
--hero-stage-exit-staggerGap between two letters leaving; 0 turns the cascade off.
--hero-stage-exit-startWhere the exit window starts (with --hero-stage-exit-end).
--hero-stage-letter-travelHow far a letter slides out of its mask (default -140%); raise it for deep descenders.

HeroStageCard

One collage photograph that arrives around the landed card, placed and sized with inset utilities (never translate-* or scale-*). Its sway derives from index; forwards all native <div> props.

PropTypeDefaultDescription
indexnumber0Place in the stagger: 0 lands first, each step a little further into the scroll. Number parts in landing order, not DOM order.
CSS variableDescription
--hero-stage-shiftVertical arrival distance (default 1.75rem); negative drops the part in from above.
--hero-stage-driftSideways arrival distance; negative arrives from the left.
--hero-stage-tiltThe lean the part arrives with and settles out of.

HeroStageReveal

A band of late copy (eyebrow, lede, CTAs, or a HeroTitle that must show at rest), placed on the vertical axis only; it centres its children. Forwards all native <div> props.

PropTypeDefaultDescription
indexnumber0Place in the stagger: 0 lands first, each step a little further into the scroll. Number parts in landing order, not DOM order.
CSS variableDescription
--hero-stage-shiftVertical arrival distance (default 1.75rem); negative drops the part in from above.
--hero-stage-driftSideways arrival distance; negative arrives from the left.
--hero-stage-tiltThe lean the part arrives with and settles out of.

HeroSpread

The editorial spread, composed instead of HeroContent inside a split hero: a picture half and a panel half, stacked below lg. Forwards all native <div> props.

HeroSpreadMedia

The picture half; covers and crops a plain <img> or <video>. Put it first so it leads on a phone; forwards all native <div> props.

HeroSpreadPanel

The inked half; give it exactly two groups and it pushes the first to the top, the second to the foot. Forwards all native <div> props.

PropTypeDefaultDescription
tone"brand" | "ink""ink"A slab pinned dark on every theme, or the raw accent. Lead with variant="neutral" over ink, Button tone="onMedia" over brand.

HeroSpreadIndex

The chapter mark ("01") in the panel's outer corner, hidden from assistive tech. Forwards all native <div> props.

PropTypeDefaultDescription
tone"brand" | "ink""ink"The panel tone it sits on, so the chip inverts with it.

HeroStatement

The section's <h1> when the hero is one sentence, used instead of HeroTitle: display scale on a ~36-character measure. Forwards all native <h1> props.

HeroSignoff

A letter's closing under the statement, one line per child; a Signature can be its last line. Forwards all native <div> props.

HeroMosaic

The picture band across the top of a hero: a twelve-track grid of HeroFrames (two tracks while stacked) gated by viewport breakpoints. Forwards all native <div> props.

HeroFrame

One rounded, cropping picture frame with a hairline over the photograph; shape it with className and drop a plain <img> in. Drifts in on mount; forwards all native <div> props.

PropTypeDefaultDescription
tone"color" | "mono""color"mono drops the colour so a wall of photographs reads as one.
delaynumber0Milliseconds before it drifts in.

FAQ#

Hero is pure layout, so it ships no controls of its own. It is composed entirely of existing Koala components: drop our Button inside `HeroActions`, an `AvatarGroup` and `Rating` in `HeroSocialProof`, and a dot `Badge` for the eyebrow, so the hero stays consistent with the rest of the design system.