Skip to content
Facade UI
Colour mode
GitHub (opens in a new tab)
blockmotion

CTA band (motion)

Closing CTA revealed as it scrolls into view.

Wraps the static CTA band, which renders identically with JavaScript disabled.

Preview

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

Installation

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

Pulls in cta-band, motion-primitives. The CLI installs them for you.

Usage

The exact source of the preview above.

demos/cta-band-motion.tsx
"use client"

/**
 * The `cta-band` 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 { CtaBandMotion } from "@registry/sections/cta-band-motion"

import { ACTIONS } from "./content"

export function Demo() {
  return (
    <div className="flex flex-col gap-10">
      <CtaBandMotion
        title="Ready when you are"
        description="Install the first section and see how it sits in your own theme."
        actions={ACTIONS}
        note="No account required."
        spacing="none"
      />
      <CtaBandMotion
        variant="primary"
        layout="split"
        title="Or start from a template"
        description="Whole pages, assembled from the same sections."
        actions={[{ label: "Browse templates", href: "#templates" }]}
        spacing="none"
      />
    </div>
  )
}

Source

What the CLI copies into your project, byte for byte.

components/sections/cta-band-motion.tsx
"use client"

/**
 * CtaBandMotion — the closing CTA revealed as it scrolls into view.
 *
 * Unlike the heroes, this stack plays on scroll rather than on mount, because a
 * closing band is below the fold by definition.
 *
 * Dependencies: react, @/components/motion/slots, @/components/motion/stagger,
 * @/components/sections/cta-band.
 */

import type { ReactNode } from "react"

import { StaggerBlock } from "@/components/motion/slots"
import { Stagger } from "@/components/motion/stagger"
import { CtaBand, type CtaBandProps } from "@/components/sections/cta-band"

function RevealStack({
  className,
  children,
}: {
  className?: string
  children?: ReactNode
}) {
  return (
    <Stagger className={className} stagger={0.08}>
      {children}
    </Stagger>
  )
}

export type CtaBandMotionProps = Omit<CtaBandProps, "stackAs" | "blockAs">

export function CtaBandMotion(props: CtaBandMotionProps) {
  return <CtaBand {...props} stackAs={RevealStack} blockAs={StaggerBlock} />
}

Props

CtaBandMotionProps

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