designmotionhq

interaction

Accordion Disclosure

One accordion glides open, the other jumps. Four small rules separate them.

Watch on Instagram

Key insights

  • You can't animate height: auto — the transition just snaps. Use display: grid with grid-template-rows going from 0fr to 1fr, or measure scrollHeight and animate to a pixel value.
  • Drive the chevron rotation from the same timing curve as the panel. Even ~10 frames of lag between the two reads as broken, not smooth.
  • Decide single vs multi open: an accordion lets one panel open at a time, a disclosure lets many stay open. Sequential steps stay single; FAQ lists let several breathe.
  • The header is a <button>, not a <div>. Wire aria-expanded to reflect state and aria-controls to point at the panel, so Enter/Space toggle it and the focus ring shows.
  • When an item near the bottom expands, anchor the tapped header so the list doesn't jump under the user, and stagger the revealed content in.

Do / Don't

  • Do: Drive chevron rotation and panel height from one shared timing curve so they move as a unit
  • Do: Render the header as a real <button> with aria-expanded and aria-controls wired to the panel
  • Do: Match open behavior to content — one-at-a-time for steps, many-open for FAQ lists
  • Don't: Animate height: auto and expect a transition — use grid rows or a measured pixel height
  • Don't: Let the chevron trail the panel; even a few frames of lag feels janky
  • Don't: Let the list scroll-jump when a lower item expands — keep the tapped header anchored

Want Claude to build this correctly?

UX Engine gives Claude Code the senior-designer reasoning behind every pattern.

The Design System Blueprint

An 11-page visual guide to consistent, scalable UI: colors, typography, spacing, components, motion.

Get the Blueprint — free

The PDF, plus emails about new patterns and my tools. Unsubscribe anytime.

Related patterns