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

FAQ accordion (motion)

FAQ rows revealed as they scroll in. The open/close animation needs no JavaScript.

Wraps the static FAQ accordion, 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/faq-accordion-motion.json

Pulls in faq-accordion, motion-primitives. The CLI installs them for you.

Usage

The exact source of the preview above.

demos/faq-accordion-motion.tsx
"use client"

/**
 * The `faq-accordion` 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 { FaqAccordionMotion } from "@registry/sections/faq-accordion-motion"

import { FAQS } from "./content"

export function Demo() {
  return (
    <FaqAccordionMotion
      eyebrow="FAQ"
      title="Questions, answered"
      items={FAQS}
      defaultOpen={["faq-is-facade-ui-free"]}
      align="center"
      schemaOrg
    />
  )
}

Source

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

components/sections/faq-accordion-motion.tsx
"use client"

/**
 * FaqAccordionMotion — the FAQ with its rows revealed as they scroll in.
 *
 * The open/close animation is *not* what this adds: Base UI plus the CSS height
 * transition already handles that, without JavaScript. What the motion variant
 * contributes is the entrance of the list itself.
 *
 * Dependencies: react, @/components/motion/slots,
 * @/components/sections/faq-accordion.
 */

import type { ReactNode } from "react"

import { StaggerBlock } from "@/components/motion/slots"
import { Stagger } from "@/components/motion/stagger"
import { FaqAccordion, type FaqAccordionProps } from "@/components/sections/faq-accordion"

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

export type FaqAccordionMotionProps = Omit<FaqAccordionProps, "listAs" | "itemAs">

export function FaqAccordionMotion(props: FaqAccordionMotionProps) {
  return <FaqAccordion {...props} listAs={RevealStack} itemAs={StaggerBlock} />
}

Props

FaqAccordionMotionProps

Extends Omit<FaqAccordionProps, "listAs" | "itemAs">.