.fyi
SkillsMCPPluginsSubagents

Browse by category

DevOps & CI/CD SkillsProductivity & Workflow SkillsOther SkillsProduct & Project Management SkillsDocumentation & Knowledge SkillsCode Review & Refactor SkillsBackend & APIs SkillsAgent Meta & Communication SkillsResearch SkillsSecurity SkillsUX UI & Design SkillsTesting & QA SkillsSee all →

Every Claude Code skill, MCP server, plugin and subagent in one directory. Searchable, comparable, and one command from installed. Live stats from GitHub, npm and PyPI.

We're on Product HuntYour agent's app storeCheck it out →
Agent SkillsMCP ServersPluginsSubagentsCoding Agents
CollectionsOfficial publishersGlossaryFAQBlogSearchSavedFeedback
PrivacyTermsllms.txtSitemap

made with ♥ · © 2026 aaaa.fyi

Independent project · real data from public registries

…/agent-skills/react-view-transitions
home/skills/vercel-labs/agent-skills/react-view-transitions
vercel-labs avatar

react-view-transitions

byvercel-labs· 154 skills

Installs

88k

Stars

29k

Forks

2.6k

Category

Frontend Development

View on GitHub

TL;DR

Guide for implementing smooth, native-feeling animations using React's View Transition API (<ViewTransition> component, addTransitionType, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view transitions, startViewTransition, ViewTransition, transition types, or asks about animating between UI states in React without third-party animation libraries.

How to install react-view-transitions?

vercel-labs/agent-skills/react-view-transitions
$npx -y skills add vercel-labs/agent-skills --skill react-view-transitions

Installs into the current project.

›Prefer a prompt? Paste this to your agent

Use this skill

Run `npx skills use "https://github.com/vercel-labs/agent-skills" --skill "vercel-labs/agent-skills/react-view-transitions"` and follow the generated skill instructions now. Read its complete output, redirecting it to a temporary file first if necessary. Resolve relative paths from the supporting-files directory it provides.

Use the whole pack

Use the skills in "https://github.com/vercel-labs/agent-skills" that are relevant to the current task. Run `npx skills add "https://github.com/vercel-labs/agent-skills"` and select the relevant skills, then follow their instructions.

Files · 1

View on GitHub
SKILL.md
1# React View Transitions
2 
3Animate between UI states using the browser's native `document.startViewTransition`. Declare *what* with `<ViewTransition>`, trigger *when* with `startTransition` / `useDeferredValue` / `Suspense`, control *how* with CSS classes. Unsupported browsers skip animations gracefully.
4 
5## When to Animate
6 
7Every `<ViewTransition>` should communicate a spatial relationship or continuity. If you can't articulate what it communicates, don't add it.
8 
9Implement **all** applicable patterns from this list, in this order:
10 
11| Priority | Pattern | What it communicates |
12|----------|---------|---------------------|
13| 1 | **Shared element** (`name`) | "Same thing — going deeper" |
14| 2 | **Suspense reveal** | "Data loaded" |
15| 3 | **List identity** (per-item `key`) | "Same items, new arrangement" |
16| 4 | **State change** (`enter`/`exit`) | "Something appeared/disappeared" |
17| 5 | **Route change** (layout-level) | "Going to a new place" |
18 
19This is an implementation order, not a "pick one" list. Implement every pattern that fits the app. Only skip a pattern if the app has no use case for it.
20 
21### Choosing Animation Style
22 
23| Context | Animation | Why |
24|---------|-----------|-----|
25| Hierarchical navigation (list → detail) | Type-keyed `nav-forward` / `nav-back` | Communicates spatial depth |
26| Lateral navigation (tab-to-tab) | Bare `<ViewTransition>` (fade) or `default="none"` | No depth to communicate |
27| Suspense reveal | `enter`/`exit` string props | Content arriving |
28| Revalidation / background refresh | `default="none"` | Silent — no animation needed |
29 
30Reserve directional slides for hierarchical navigation (list → detail) and ordered sequences (prev/next photo, carousel, paginated results). For ordered sequences, the direction communicates position: "next" slides from right, "previous" from left. Lateral/unordered navigation (tab-to-tab) should not use directional slides — it falsely implies spatial depth.
31 
32---
33 
34## Availability
35 
36- **Next.js:** Do **not** install `react@canary` — the App Router already bundles React canary internally. `ViewTransition` works out of the box. `npm ls react` may show a stable-looking version; this is expected.
37- **Without Next.js:** Install `react@canary react-dom@canary` (`ViewTransition` is not in stable React).
38- Browser support: Chromium 125+ (React needs the v2 object form of `startViewTransition`), Firefox 144+, Safari 18.2+. Graceful degradation on unsupported browsers.
39 
40---
41 
42## Implementation Workflow
43 
44When adding view transitions to an existing app, **follow [references/implementation.md](references/implementation.md) step by step.** Start with the audit — do not skip it. Copy the CSS recipes from [references/css-recipes.md](references/css-recipes.md) into the global stylesheet — do not write your own animation CSS.
45 
46---
47 
48## Core Concepts
49 
50### The `<ViewTransition>` Component
51 
52```jsx
53import { ViewTransition } from 'react';
54 
55<ViewTransition>
56 <Component />
57</ViewTransition>
58```
59 
60React auto-assigns a unique `view-transition-name` and calls `document.startViewTransition` behind the scenes. Never call `startViewTransition` yourself.
61 
62### Animation Triggers
63 
64| Trigger | When it fires |
65|---------|--------------|
66| **enter** | `<ViewTransition>` first inserted during a Transition |
67| **exit** | `<ViewTransition>` first removed during a Transition |
68| **update** | DOM mutations inside a `<ViewTransition>`, or the boundary itself changing size/position due to an immediate sibling. With nested VTs, mutation applies to the innermost one |
69| **share** | Named VT unmounts and another with same `name` mounts in the same Transition |
70 
71Only `startTransition`, `useDeferredValue`, or `Suspense` activate VTs. Regular `setState` does not animate.
72 
73### Critical Placement Rule
74 
75`<ViewTransition>` only activates enter/exit if it appears **before any DOM nodes**:
76 
77```jsx
78// Works
79<ViewTransition enter="auto" exit="auto">
80 <div>Content</div>
81</ViewTransition>
82 
83// Broken — div wraps the VT, suppressing enter/exit
84<div>
85 <ViewTransition enter="auto" exit="auto">
86 <div>Content</div>
87 </ViewTransition>
88</div>
89```
90 
91---
92 
93## Styling with View Transition Classes
94 
95### Props
96 
97Values: `"auto"` (browser cross-fade), `"none"` (disabled), `"class-name"` (custom CSS), or `{ [type]: value }` for type-specific animations.
98 
99```jsx
100<ViewTransition default="none" enter="slide-in" exit="slide-out" share="morph" />
101```
102 
103If `default` is `"none"`, all triggers are off unless explicitly listed.
104 
105### CSS Pseudo-Elements
106 
107- `::view-transition-old(.class)` — outgoing snapshot
108- `::view-transition-new(.class)` — incoming snapshot
109- `::view-transition-group(.class)` — container
110- `::view-transition-image-pair(.class)` — old + new pair
111 
112See [references/css-recipes.md](references/css-recipes.md) for ready-to-use animation recipes.
113 
114---
115 
116## Transition Types
117 
118Tag transitions with `addTransitionType` so VTs can pick different animations based on context. Call it multiple times to stack types — different VTs in the tree react to different types:
119 
120```jsx
121startTransition(() => {
122 addTransitionType('nav-forward');
123 addTransitionType('select-item');
124 router.push('/detail/1');
125});
126```
127 
128Pass an object to map types to CSS classes. Works on `enter`, `exit`, **and** `share`:
129 
130```jsx
131<ViewTransition
132 enter={{ 'nav-forward': 'slide-from-right', 'nav-back': 'slide-from-left', default: 'none' }}
133 exit={{ 'nav-forward': 'slide-to-left', 'nav-back': 'slide-to-right', default: 'none' }}
134 share={{ 'nav-forward': 'morph-forward', 'nav-back': 'morph-back', default: 'morph' }}
135 default="none"
136>
137 <Page />
138</ViewTransition>
139```
140 
141`enter` and `exit` don't have to be symmetric. For example, fade in but slide out directionally:
142 
143```jsx
144<ViewTransition
145 enter={{ 'nav-forward': 'fade-in', 'nav-back': 'fade-in', default: 'none' }}
146 exit={{ 'nav-forward': 'nav-forward', 'nav-back': 'nav-back', default: 'none' }}
147 default="none"
148>
149```
150 
151**TypeScript:** `ViewTransitionClassPerType` requires a `default` key in the object.
152 
153For apps with multiple pages, extract the type-keyed VT into a reusable wrapper:
154 
155```jsx
156export function DirectionalTransition({ children }: { children: React.ReactNode }) {
157 return (
158 <ViewTransition
159 enter={{ 'nav-forward': 'nav-forward', 'nav-back': 'nav-back', default: 'none' }}
160 exit={{ 'nav-forward': 'nav-forward', 'nav-back': 'nav-back', default: 'none' }}
161 default="none"
162 >
163 {children}
164 </ViewTransition>
165 );
166}
167```
168 
169### `router.back()` and Browser Back Button
170 
171`router.back()` and the browser's back/forward buttons carry **no transition types**, so type-keyed animations (directional slides) resolve to their `default` and don't play — untyped shared-element morphs still apply. For typed animations, use `router.push()` with an explicit URL.
172 
173### Types and Suspense
174 
175Types are available during navigation but **not** during subsequent Suspense reveals (separate transitions, no type). Use type maps for page-level enter/exit; use simple string props for Suspense reveals.
176 
177---
178 
179## Shared Element Transitions
180 
181Same `name` on two VTs — one unmounting, one mounting — creates a shared element morph:
182 
183```jsx
184<ViewTransition name="hero-image">
185 <img src="/thumb.jpg" onClick={() => startTransition(() => onSelect())} />
186</ViewTransition>
187 
188// On the other view — same name
189<ViewTransition name="hero-image">
190 <img src="/full.jpg" />
191</ViewTransition>
192```
193 
194- Only one VT with a given `name` can be mounted at a time — use unique names (`photo-${id}`). Watch for reusable components: if a component with a named VT is rendered in both a modal/popover *and* a page, both mount simultaneously and break the morph. Either make the name conditional (via a prop) or move the named VT out of the shared component into the specific consumer.
195- `share` takes precedence over `enter`/`exit`. Think through each navigation path: when no matching pair forms (e.g., the target page doesn't have the same name), `enter`/`exit` fires instead. Consider whether the element needs a fallback animation for those paths.
196- Two ways a wired-up morph silently never fires: (1) `default="none"` with no explicit `share` prop — share resolves to none; (2) type-keyed `share` where the navigation never adds the type — a plain link click resolves the map's `default`. Every link that should morph must add the type (`transitionTypes` on `next/link`, or `addTransitionType`).
197- Never use a fade-out exit on pages with shared morphs — use a directional slide instead.
198 
199---
200 
201## Common Patterns
202 
203### Enter/Exit
204 
205```jsx
206{show && (
207 <ViewTransition enter="fade-in" exit="fade-out"><Panel /></ViewTransition>
208)}
209```
210 
211### List Reorder
212 
213```jsx
214{items.map(item => (
215 <ViewTransition key={item.id}><ItemCard item={item} /></ViewTransition>
216))}
217```
218 
219Trigger inside `startTransition`. Avoid wrapper `<div>`s between list and VT.
220 
221### Layout Displacement Morph
222 
223Only content inside an activated boundary animates position — everything else teleports to its new layout spot. Wrap the sibling content below a growing/shrinking list in a bare `<ViewTransition>` so it glides instead of jumping. See [Layout Displacement Morph](references/patterns.md#layout-displacement-morph).
224 
225### Composing Shared Elements with List Identity
226 
227Shared elements and list identity are independent concerns — don't confuse one for the other. When a list item contains a shared element (e.g., an image that morphs into a detail view), use two nested `<ViewTransition>` boundaries:
228 
229```jsx
230{items.map(item => (
231 <ViewTransition key={item.id}> {/* list identity */}
232 <Link href={`/items/${item.id}`}>
233 <ViewTransition name={`item-image-${item.id}`} share="morph"> {/* shared element */}
234 <Image src={item.image} />
235 </ViewTransition>
236 <p>{item.name}</p>
237 </Link>
238 </ViewTransition>
239))}
240```
241 
242The outer VT handles list reorder/enter animations. The inner VT handles the cross-route shared element morph. Missing either layer means that animation silently doesn't happen.
243 
244### Force Re-Enter with `key`
245 
246```jsx
247<ViewTransition key={searchParams.toString()} enter="slide-up" default="none">
248 <ResultsGrid />
249</ViewTransition>
250```
251 
252**Caution:** If wrapping `<Suspense>`, changing `key` remounts the boundary and refetches.
253 
254### Suspense Fallback to Content
255 
256Simple cross-fade:
257```jsx
258<ViewTransition>
259 <Suspense fallback={<Skeleton />}><Content /></Suspense>
260</ViewTransition>
261```
262 
263Directional reveal:
264```jsx
265<Suspense fallback={<ViewTransition exit="slide-down"><Skeleton /></ViewTransition>}>
266 <ViewTransition enter="slide-up" default="none"><Content /></ViewTransition>
267</Suspense>
268```
269 
270For more patterns, see [references/patterns.md](references/patterns.md).
271 
272---
273 
274## How Multiple VTs Interact
275 
276Every VT matching the trigger fires simultaneously in a single `document.startViewTransition`. VTs in **different** transitions (navigation vs later Suspense resolve) don't compete.
277 
278### Use `default="none"` Deliberately
279 
280Without it, every VT fires the browser cross-fade on **every** transition — Suspense resolves, `useDeferredValue` updates, background revalidations. Use `default="none"` on named/shared elements and type-keyed page VTs.
281 
282But it also turns off `update` (layout/reflow morphs) and `share` (a named pair with no explicit `share` prop never morphs). Keyed list items and displaced siblings *want* update — leave them bare or set `update="auto"`.
283 
284### Two Patterns Coexist
285 
286**Pattern A — Directional slides:** Type-keyed VT on each page, fires during navigation.
287**Pattern B — Suspense reveals:** Simple string props, fires when data loads (no type).
288 
289They coexist because they fire at different moments. `default="none"` on both prevents cross-interference. Always pair `enter` with `exit`. Place directional VTs in page components, not layouts.
290 
291### Nested VT Limitation
292 
293When a parent VT mounts/unmounts **as one unit** with nested VTs inside it, the nested ones do not fire their own enter/exit — only the outermost VT animates. (A child VT mounted inside a *persistent* parent VT fires enter/exit normally.) Per-item staggered animations during page navigation are not possible today; the experimental opt-in is the `parentEnter`/`parentExit` props ([react#36690](https://github.com/facebook/react/pull/36690), experimental channel only).
294 
295---
296 
297## Next.js Integration
298 
299For Next.js setup (`experimental.viewTransition` flag, `transitionTypes` prop on `next/link`, App Router patterns, Server Components), see [references/nextjs.md](references/nextjs.md).
300 
301---
302 
303## Accessibility
304 
305Always add the reduced motion CSS from [references/css-recipes.md](references/css-recipes.md#reduced-motion) to your global stylesheet.
306 
307---
308 
309## Reference Files
310 
311- **[references/implementation.md](references/implementation.md)** — Step-by-step implementation workflow.
312- **[references/patterns.md](references/patterns.md)** — Patterns, animation timing, events API, troubleshooting.
313- **[references/css-recipes.md](references/css-recipes.md)** — Ready-to-use CSS animation recipes.
314- **[references/nextjs.md](references/nextjs.md)** — Next.js App Router patterns and Server Component details.
315 
316## Full Compiled Document
317 
318For the complete guide with all reference files expanded: `AGENTS.md`

Preview

vercel-labs/agent-skillsvercel-labs/agent-skills

$ npx -y skills add vercel-labs/agent-skills --skill react-view-transitions

▸ installing to .claude/skills…

✓ react-view-transitions ready

Repovercel-labs/agent-skills
TypeSkills
CategoryFrontend Development
ForDeveloperDesigner
UpdatedJul 2026
License—
First seenJul 26, 2026

Tags

Skill

Related

6 picks
Type
  1. vercel-labs avatarreact-best-practicesReact and Next.js performance optimization guidelines from Vercel Engineering.SkillsJul 2026587k29k
  2. heygen-com avatarhyperframes-registryInstall, discover, and wire registry blocks and components into HyperFrames compositions.SkillsJul 2026267k38k
  3. vercel-labs avatarcomposition-patternsReact composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing…SkillsJul 2026266k29k
  4. shadcn avatarshadcnManages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI, including chat interfaces.SkillsJul 2026257k120k
  5. larksuite avatarlark-apps妙搭(Spark/Miaoda)应用开发与托管:应用创建、本地全栈开发、云端生成迭代、创意设计(UI mockup / 可交互原型 / 线框图 / 落地页 / 仪表盘 / 幻灯片 deck / 视觉探索)、AI相关能力和飞书平台能力或者其他外部能力集成、日志/Trace/监控指标/PV/UV…SkillsJul 2026235k16k
  6. leonxlnx avatarimage-to-code-skillElite website image-to-code skill for Codex. For visually important web tasks, it must first generate the design image(s) itself, deeply analyze them, then…SkillsJul 2026175k68k