Adopt View Transitions for auto-height disclosures (the one sanctioned layout animation)
- Dominant language
- TypeScript
- Stars
- 13.1k
- Forks
- 1.1k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 669
Description
## The problem
Astryx's motion convention says animate only `transform` and `opacity` — those are composited, and everything else (`width`, `height`, `margin`, `grid-template-rows`) makes the browser recompute layout every frame.
There is exactly one case the rule cannot accommodate: **revealing an element to an unknown height.** No transform expresses "grow from nothing to however tall the content happens to be." `scaleY` distorts the content and leaves siblings unmoved; opacity alone gives no reveal; a JS-measured `max-height` costs the same layout plus script.
So today the sanctioned pattern is animating `grid-template-rows` between `1fr` and `0fr` with `overflow: hidden` on the inner element — a deliberate layout animation, bounded by keeping the subtree small, the interaction user-initiated and brief, and reduced motion honoured. `SideNavItem`'s collapsible group is the live example.
## Why view transitions are the way out
The View Transitions API snapshots the before and after states and animates the **snapshots** on their own layer. The reveal becomes composited and the document does not re-lay-out per frame. It is a different animation model, which is why no CSS property was ever going to solve this — including `interpolate-size` / `calc-size()`, which just let you animate `height: auto` directly and are the same reflow with nicer syntax.
**Browser support is no longer the blocker** — Chrome 111, Safari 18, Firefox 144, so all three engines ship it.
## The open question: React
`` is **canary-only**. Astryx ships against stable React, so this is not adoptable yet, and that is the thing to work out:
- Is `document.startViewTransition()` usable directly, coordinating with React's commit ourselves, or does that fight the reconciler badly enough to wait?
- If we wait — what is the trigger? A stable release, or an earlier signal that the API has settled?
- Does a component library even own this, or does the host app? A view transition is document-scoped by default; a design system component starting one has effects outside itself. Scoped view transitions change that answer, so their status matters here too.
## Also worth knowing before adopting
View transitions scale the old and new snapshots to fit the group, which **distorts content whose aspect ratio changes** — the classic squish. For a disclosure, that is precisely the axis that changes, so the migration needs a look at real components rather than a find-and-replace.
## What would close this
A decision on the three questions above, and if the answer is "adopt": a shared helper so components do not each hand-roll the coordination, plus a migration of the existing disclosure animations.
Until then the layout-animation exception stands, documented in the Component Audit Rubric under D12:
https://github.com/facebook/astryx/wiki/Component-Audit-Rubric
Contributor guide
Research direction
Start with the SideNavItem collapsible group and the Component Audit Rubric's D12 guidance, then investigate stable React coordination with document.startViewTransition() and the status of scoped view transitions. Done means deciding whether and where to adopt the API; if adoption is chosen, define a shared helper and migrate the existing disclosure animations after checking real components for snapshot distortion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- design, frontend, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100