Skip to content

feat(native): view transitions with a named pair of screens - #55

Open
mateo-m wants to merge 121 commits into
remorses:mainfrom
mateo-m:feat/view-transitions
Open

feat(native): view transitions with a named pair of screens#55
mateo-m wants to merge 121 commits into
remorses:mainfrom
mateo-m:feat/view-transitions

Conversation

@mateo-m

@mateo-m mateo-m commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Stacked on #54 (fix/selection-remount-automation).

What this adds

The View Transitions API. startViewTransition(renderer, update, options) captures every element that carries a viewTransitionName style, applies the React update synchronously, and animates each name from its old place to its new one.

  • The renderer clones the named subtrees before the update. It paints the frozen copies over the live tree while the transition runs. So the leaving screen stays visible under, or over, the arriving one.
  • Options take a duration, a delay, and an ease per name, plus translateX, translateY and opacity ranges for the old side and the new side. Percent lengths resolve against the size of the named element, so translateX: ["100%", "0%"] slides a screen in from the right at any width.
  • A name with no options crossfades. A name that only enters animates against its own bounds.
  • The new side moves through the motion channel at prepaint, so the hitboxes move with the pixels and input lands where the screen paints.
  • A frozen copy takes fresh ids where the live tree still uses them, so a surviving element and its copy never share GPUI element state. Ids of destroyed elements stay, so their scroll offsets survive the swap.

Demo

The Navigation panel in examples/demo is the push and pop of the iOS Settings app. A click on General slides its screen in from the right while Settings slides 30% of its width to the left. The back button runs the same move backwards with the leaving screen on top.

Limits in this version

  • A name that only leaves paints nothing.
  • The frozen copy takes no input.

Tests

  • packages/react/src/__tests__/view-transitions.test.tsx: the push pair, the default crossfade, an enter-only name, a restart mid-flight, an update in place, and a renderer without the native methods. 6 tests.
  • examples/demo.test.tsx: a real click drives the push, the screen starts 318px to the right, and the pop returns to the root screen.
  • Full suites: packages/react 439 passed, examples 56 passed, cargo test ok.

Moved from the fork

This PR was mateo-m#7.

The branch merged its parent branch after that one merged upstream main at 028f70a.

The history was rewritten once after the first push. It dropped the commits that reworded AGENTS.md, and the zed pin moved to the rewritten mateo-m/zed branches. No code changed in that rewrite.

On the merged head cargo check and tsc pass. The full suites ran at the bottom and at the top of the stack.

Stacked on #54. The diff here includes #50, #51, #52, #53, #54.

The zed submodule points at the mateo-m/zed fork until remorses/zed#5, #6 and #7 merge. Then a follow-up commit restores .gitmodules to remorses/zed on the gpuix branch and pins the merged commit. The same GPUI stack is also open upstream as zed-industries/zed#63771, #63772 and #63773.

mateo-m added 30 commits August 25, 2026 16:59
mateo-m added 15 commits August 29, 2026 18:29
# Conflicts:
#	.github/workflows/ci.yml
#	examples/compile.ts
#	packages/native/src/custom_elements/anchored.rs
#	packages/native/src/custom_elements/code.rs
#	packages/native/src/custom_elements/diff.rs
#	packages/native/src/custom_elements/img.rs
#	packages/native/src/custom_elements/input.rs
#	packages/native/src/custom_elements/markdown.rs
#	packages/native/src/renderer.rs
#	packages/react/src/types/host.ts
#	zed
# Conflicts:
#	packages/native/src/custom_elements/code.rs
#	packages/native/src/renderer/frame.rs
#	packages/native/src/style/resolve.rs
#	packages/react/src/testing.ts
#	packages/react/src/types/host.ts
# Conflicts:
#	packages/native/src/renderer/frame.rs
#	packages/react/src/reconciler/event-registry.ts
# Conflicts:
#	packages/react/src/testing.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant