Motion+

Accordion

An example of an accordion component using Motion for React. Animate accordion content using height: auto and accessible markup. Uses focus events and shared layout animations for keyboard accessibility.

React
Tutorial time
5 min
Difficulty

Tutorial

Introduction

The Accordion example shows how to build an accessible accordion component with smooth animations. Each item can expand and collapse to reveal content, with animated height transitions and visual effects.

This tutorial uses several Motion APIs: the animate prop to control animation states, variants to define reusable animation configurations, layoutId for the shared focus ring animation, and the MotionConfig component to set default animation options across multiple elements.

Motion makes animating height: auto easy, which is normally difficult with CSS alone. The example also demonstrates how to combine multiple animated properties like height, opacity, and filter to create polished UI transitions.

Get Started

Let's start with the basic accordion structure. We'll create an Item component that displays a header and content:

import { useState } from "react"

function Item({ header, children }) {
    const [isOpen, setIsOpen] = useState(false)

    return (
        <section>
            <h3>
                <button onClick={() => setIsOpen(!isOpen)}>
                    <span>{header}</span> <ChevronDownIcon />
                </button>
            </h3>
            <div className="accordion-content">
                <div>{children}</div>
            </div>
            <hr />
        </section>
    )
}

export default function Accordion() {
    return (
        <div className="accordion">
            <Item header="What is Motion+?">
                <p>
                    Motion+ is a one-time fee, lifetime access membership that
                    unlocks the source code for all Motion examples, early
                    access features, premium components, and an exclusive
                    Discord community.
                </p>
            </Item>
            <Item header={`What does "lifetime access" mean?`}>
                <p>
                    Just that! No one needs another subscription in their life.
                </p>
                <p>
                    {`Lifetime access means you'll receive all updates to Motion+ as they're released.`}
                </p>
            </Item>
            <Item header="How does the team package work?">
                <p>
                    After purchase, you can nominate up to 10 team members to
                    join Motion+.
                </p>
            </Item>
        </div>
    )
}

/** Copy styles and icons from example source code */

We're using React's useState to track whether each item is open or closed. Clicking the button toggles the isOpen state.

Related examples

Latest in React

Motion+

Unlock all 400+ examples

  • Source code for every Plus example.
  • Provide examples direct to your agent via Motion's MCP.
  • Lifetime access to new examples and APIs.