Install
$ agentstack add skill-ariadoss-superskills-react-view-transitions ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README — it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming — see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps — measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
React View Transitions
Animate between UI states using the browser's native document.startViewTransition. Declare what with `, trigger *when* with startTransition / useDeferredValue / Suspense`, control how with CSS classes. Unsupported browsers skip animations gracefully.
When to Animate
Every `` should communicate a spatial relationship or continuity. If you can't articulate what it communicates, don't add it.
Implement all applicable patterns from this list, in this order:
| Priority | Pattern | What it communicates | |----------|---------|---------------------| | 1 | Shared element (name) | "Same thing — going deeper" | | 2 | Suspense reveal | "Data loaded" | | 3 | List identity (per-item key) | "Same items, new arrangement" | | 4 | State change (enter/exit) | "Something appeared/disappeared" | | 5 | Route change (layout-level) | "Going to a new place" |
This 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.
Choosing Animation Style
| Context | Animation | Why | |---------|-----------|-----| | Hierarchical navigation (list → detail) | Type-keyed nav-forward / nav-back | Communicates spatial depth | | Lateral navigation (tab-to-tab) | Bare ` (fade) or default="none" | No depth to communicate | | Suspense reveal | enter/exit string props | Content arriving | | Revalidation / background refresh | default="none"` | Silent — no animation needed |
Reserve 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.
Availability
- Next.js: Do not install
react@canary— the App Router already bundles React canary internally.ViewTransitionworks out of the box.npm ls reactmay show a stable-looking version; this is expected. - Without Next.js: Install
react@canary react-dom@canary(ViewTransitionis not in stable React). - Browser support: Chromium 111+, Firefox 144+, Safari 18.2+. Graceful degradation on unsupported browsers.
Core Concepts
The `` Component
import { ViewTransition } from 'react';
React auto-assigns a unique view-transition-name and calls document.startViewTransition behind the scenes. Never call startViewTransition yourself.
Animation Triggers
| Trigger | When it fires | |---------|--------------| | enter | ` first inserted during a Transition | | **exit** | first removed during a Transition | | **update** | DOM mutations inside a . With nested VTs, mutation applies to the innermost one | | **share** | Named VT unmounts and another with same name` mounts in the same Transition |
Only startTransition, useDeferredValue, or Suspense activate VTs. Regular setState does not animate.
Critical Placement Rule
`` only activates enter/exit if it appears before any DOM nodes:
// Works
Content
// Broken — div wraps the VT, suppressing enter/exit
Content
Styling with View Transition Classes
Props
Values: "auto" (browser cross-fade), "none" (disabled), "class-name" (custom CSS), or { [type]: value } for type-specific animations.
If default is "none", all triggers are off unless explicitly listed.
CSS Pseudo-Elements
::view-transition-old(.class)— outgoing snapshot::view-transition-new(.class)— incoming snapshot::view-transition-group(.class)— container::view-transition-image-pair(.class)— old + new pair
Transition Types
Tag 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:
startTransition(() => {
addTransitionType('nav-forward');
addTransitionType('select-item');
router.push('/detail/1');
});
Pass an object to map types to CSS classes. Works on enter, exit, and share:
TypeScript: ViewTransitionClassPerType requires a default key in the object.
For apps with multiple pages, extract the type-keyed VT into a reusable wrapper:
export function DirectionalTransition({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
router.back() and Browser Back Button
router.back() and the browser's back/forward buttons do not trigger view transitions (popstate is synchronous, incompatible with startViewTransition). Use router.push() with an explicit URL instead.
Shared Element Transitions
Same name on two VTs — one unmounting, one mounting — creates a shared element morph:
startTransition(() => onSelect())} />
// On the other view — same name
- Only one VT with a given
namecan be mounted at a time — use unique names (photo-${id}). sharetakes precedence overenter/exit. When no matching pair forms,enter/exitfires instead.- Never use a fade-out exit on pages with shared morphs — use a directional slide instead.
Common Patterns
Enter/Exit
{show && (
)}
List Reorder
{items.map(item => (
))}
Trigger inside startTransition. Avoid wrapper ``s between list and VT.
Composing Shared Elements with List Identity
{items.map(item => (
{/* list identity */}
{/* shared element */}
{item.name}
))}
Force Re-Enter with key
Caution: If wrapping `, changing key` remounts the boundary and refetches.
Suspense Fallback to Content
Simple cross-fade:
}>
Directional reveal:
}>
How Multiple VTs Interact
Every VT matching the trigger fires simultaneously in a single document.startViewTransition. VTs in different transitions (navigation vs later Suspense resolve) don't compete.
Use default="none" Liberally
Without it, every VT fires the browser cross-fade on every transition — Suspense resolves, useDeferredValue updates, background revalidations. Always use default="none" and explicitly enable only desired triggers.
Two Patterns Coexist
Pattern A — Directional slides: Type-keyed VT on each page, fires during navigation. Pattern B — Suspense reveals: Simple string props, fires when data loads (no type).
They 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.
Nested VT Limitation
When a parent VT exits, nested VTs inside it do not fire their own enter/exit — only the outermost VT animates. Per-item staggered animations during page navigation are not possible today.
Accessibility
Always add the reduced motion CSS to your global stylesheet:
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ariadoss
- Source: ariadoss/superskills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.