facebook / facebook/astryx

Adopt View Transitions for auto-height disclosures (the one sanctioned layout animation)

Open
#4,882 0 comments 0 reactions 0 assignees View on GitHub
enhancement needs-scoping
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.