Skip to content
Facade UI
blockmotion

Hero — split (motion)

The split hero, with its parts appearing one after another when the page loads.

Open in v0 (opens in a new tab)

This is the animated version of Hero — split. The static version looks the same with JavaScript turned off.

Preview

Open full width (opens in a new tab)
Preview width

Installation

Package manager
pnpm dlx shadcn@latest add https://facadeui.dev/r/hero-split-motion.json

This component needs hero-split, motion-primitives. The CLI installs them for you.

Usage

This is the code for the preview above. To install it as a file, run npx shadcn@latest add @facade/hero-split-motion-demo.

demos/hero-split-motion.tsx
"use client"

/**
 * The `hero-split` demo, with the motion variant swapped in.
 *
 * Identical props: the motion variant only changes which slot components
 * the static section renders through.
 *
 * `"use client"` is required here, not incidental: the motion variant is a
 * client component, and icon components cannot cross a server-to-client
 * boundary as props. See the note on `IconComponent`.
 */

import { HeroSplitMotion } from "@registry/sections/hero-split-motion"

import { ACTIONS, MediaPlaceholder } from "./content"

export function Demo() {
  return (
    <HeroSplitMotion
      eyebrow="Sections"
      title="Build the page, not the primitives"
      description="Every section takes typed content and slots, so assembling a landing page is composition rather than another round of copy-paste."
      actions={ACTIONS}
      note="Works in any React 19 project."
      media={<MediaPlaceholder label="Product screenshot" />}
      headingLevel={1}
      spacing="md"
    />
  )
}

Source

These are the files the CLI copies into your project.

components/sections/hero-split-motion.tsx
"use client"

/**
 * HeroSplitMotion — the split hero with a staggered entrance.
 *
 * A genuine wrapper: it renders the static `HeroSplit` and only swaps the stack
 * slots. Nothing visual and no accessibility decision is duplicated, so the two
 * variants cannot drift apart.
 *
 * The stagger plays on mount rather than on scroll — a hero is above the fold by
 * definition, and waiting for an intersection that already happened would just
 * leave it invisible for a frame.
 *
 * Dependencies: react, @/components/motion/slots,
 * @/components/sections/hero-split.
 */

import { StaggerBlock, StaggerStack } from "@/components/motion/slots"
import { HeroSplit, type HeroSplitProps } from "@/components/sections/hero-split"

export type HeroSplitMotionProps = Omit<HeroSplitProps, "stackAs" | "blockAs">

export function HeroSplitMotion(props: HeroSplitMotionProps) {
  return <HeroSplit {...props} stackAs={StaggerStack} blockAs={StaggerBlock} />
}

Props

HeroSplitMotionProps

Extends Omit<HeroSplitProps, "stackAs" | "blockAs">.