Skip to content
Facade UI
blockmotion

CTA band (motion)

The CTA band, appearing as you scroll to it.

Open in v0 (opens in a new tab)

This is the animated version of CTA band. 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/cta-band-motion.json

This component needs cta-band, 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/cta-band-motion-demo.

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

These are the files the CLI copies into your project.

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">.