#362
Height spring
An FAQ accordion whose panels open and close with a spring on their height, overshooting slightly before they settle.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Height spring" pattern (@codeatlasdev/ui demo #362, motion/transitions) in my app.
Call get_demo({ ids: ["#362"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Disclosure panels, FAQs and expandable table rows where a CSS ease feels stiff and the content height is not known in advance.
Keep these library parts, with the props and tokens the demo uses:
- MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` with `label="Height spring: accordion panels open and close with a spring"` and `loop={2200}`
- One `new Spring(0, { stiffness: 0.18, damping: 0.72 })` per panel drives the height in px; its target is the measured `scrollHeight` when open and `0` when closed
- A `ResizeObserver` keeps the target correct when the text wraps differently
- The clipped box reads `block-size: var(--h)` and a closed panel is `inert`
- The chevron rotates with `transition: transform 240ms cubic-bezier(0.2, 0, 0, 1)`
- Under reduced motion the spring is set with `{ instant: true }`
Exact motion (do not approximate):
- block-size of the panel: stiffness: 0.18, damping: 0.72, spring { stiffness: 0.18, damping: 0.72 }
- transform: rotate of the chevron: 240ms, cubic-bezier(0.2, 0, 0, 1)
Reduced motion: the demo handles it; keep that branch.
Keyboard: operable; keep the focus order and key handling.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` with `label="Height spring: accordion panels open and close with a spring"` and `loop={2200}`
- One `new Spring(0, { stiffness: 0.18, damping: 0.72 })` per panel drives the height in px; its target is the measured `scrollHeight` when open and `0` when closed
- A `ResizeObserver` keeps the target correct when the text wraps differently
- The clipped box reads `block-size: var(--h)` and a closed panel is `inert`
- The chevron rotates with `transition: transform 240ms cubic-bezier(0.2, 0, 0, 1)`
- Under reduced motion the spring is set with `{ instant: true }`
Related
Loading source.