view-transitions
Teaches the View Transitions API for animating DOM changes. Use when you want smooth animated transitions between pages or UI states without manual animation code.
What this skill does
# Animating View Transitions
## Table of Contents
- [When to Use](#when-to-use)
- [Instructions](#instructions)
- [Details](#details)
- [Source](#source)
## When to Use
- Use this when you want to animate transitions between different page states or navigations
- This is helpful for creating polished, app-like navigation experiences in web applications
## Instructions
- Use `document.startViewTransition(callback)` to animate DOM changes
- Assign unique `view-transition-name` CSS properties to elements that should transition between states
- Check for browser support before using the API (`if (document.startViewTransition)`)
- Minimize the time the DOM is frozen by starting transitions after data fetching completes
- Consider CSS animation fallbacks for browsers that don't yet support the View Transitions API
## Details
### Introduction to View Transitions
The [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) offers a simple way to transition any visual DOM change from one state to the next. This might include small changes such as toggling some content, or broader changes such as navigating from one page to the next.
The JavaScript API centers around `document.startViewTransition(callback)`, where `callback` is a function that typically updates the DOM to the new state.
Let's take toggling a `<details>` element as a simple example:
```js
if (document.startViewTransition) {
// (check for browser support)
document.addEventListener("click", function (event) {
if (event.target.matches("summary")) {
event.preventDefault(); // (we'll toggle the element ourselves)
const details = event.target.closest("details");
document.startViewTransition(() => details.toggleAttribute("open"));
}
});
}
```
`document.startViewTransition` takes a screenshot of the current DOM before calling the callback. Here, our callback just toggles the `open` attribute. Once complete, the browser can then transition between the initial screenshot and the new version.
These old and new versions are presented as pseudo elements and can be referenced in CSS with `::view-transition-old(root)` and `::view-transition-new(root)` respectively. For example, to emphasize the transition, we can lengthen the `animation-duration` like so:
```css
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 2s;
}
```
View transitions are also capable of animating multiple changes with more advanced animations that go beyond the default crossfade. By giving specific elements a CSS `view-transition-name`, and a `containment` of `layout` or `paint`, the API gives developers granular control over how the elements transition, including their width, height, and position. These advanced transitions can really help communicate the flow from one page to the next.
Take a photo gallery as an example: the most obvious transition is the size and position of the photo, which is automatically achieved when the `<img>` element on each page is given the same unique `view-transition-name`, and a CSS `containment` value of `layout`. The `view-transition-name`s can be hard-coded in the style attributes, or added dynamically (e.g. in a `onclick` handler), as long as they're unique to the page and added before the transition is started.
The photo details beneath require a little more styling. We give each line element its own `view-transition-name`:
```css
figcaption h2 {
contain: layout;
view-transition-name: photo-heading;
}
figcaption div {
contain: layout;
view-transition-name: photo-location-time;
}
figcaption dl {
contain: layout;
view-transition-name: photo-meta;
}
```
This generates _transition groups_ for each area, which are just like the new/old screenshots mentioned earlier, but only cover an area of the page rather than the whole document. And just as the whole document transition elements could be targeted with `::view-transition-old(root)` and `::view-transition-new(root)`, these transition groups can be targeted with `::view-transition-old(NAME)` and `::view-transition-new(NAME)`. Note that the details text is not present on the photo grid page, therefore when transitioning from the grid to the photo page, there'll only be a `::view-transition-new(NAME)`, _not_ a `::view-transition-old(NAME)`, and vice versa when navigating the other way. So we can target these cases using the `:only-child` pseudo class and customize the animation. For the `photo-heading` group:
```css
/* Enter */
::view-transition-new(photo-heading):only-child {
animation: 300ms ease 50ms both fade-in, 300ms ease 50ms both slide-up;
}
/* Exit */
::view-transition-old(photo-heading):only-child {
animation: 200ms ease 150ms both fade-out, 200ms ease 150ms both slide-down;
}
```
That's the basics of the API. [Jake Archibald's excellent View Transitions article](https://developer.chrome.com/docs/web-platform/view-transitions) covers the details well. For now, let's see how we might transition full page navigations.
### Page Navigations
A typical page navigation looks something like:
1. User clicks a link
2. Request is made for data
3. DOM is updated with the response
To apply a view transition in this flow, there are a couple of considerations.
First, is minimizing the time that the screen is in a frozen state. You may have noticed that once a view transition has started, the DOM will be not interactive until the callback completes. If we start the transition when the user clicks the link, they could be waiting a while with a frozen UI. To minimize this annoyance, ideally `document.startViewTransition` should be called after the request has completed. That way, we're ready for the change, and the DOM can be updated as swiftly as possible.
Second, we need to be sure the initial DOM screenshot has been captured before we update the DOM. When working with page navigations in third-party frameworks, we don't have full control over the rendering process; the DOM is automatically updated when the response is received. Therefore we don't have a standalone function we can pass to `document.startViewTransition` that will tidily perform the DOM update. We may need to intercept, pause, and resume rendering to give the illusion we have a single function that updates the DOM.
Nicely enough, if we return a promise from our DOM update callback, the view transition API will wait for its resolution before performing the animation. We can use this feature to handle the timing issues mentioned above.
#### React Component Example
To tackle the issues above, we'll create a React class component as it's easier to explain the flow compared to a functional component. We'll use the following lifecycle methods to control rendering:
- `shouldComponentUpdate`: we'll return `false` here and start the view transition — this will buy us some time for the screenshot capture to complete
- `forceUpdate`: to manually re-render the component after the screenshot capture
- `componentDidUpdate`: to notify the view transition API that the DOM has updated
Here's how it looks:
```js
import { Component } from "react";
export default class ViewTransition extends Component {
shouldComponentUpdate() {
if (!document.startViewTransition) return true; // skip when not supported
document.startViewTransition(() => this.#updateDOM());
return false; // don't update the component, we'll do this manually
}
#updateDOM() {
// now we know the screenshot has been taken, we can force render
// (which skips `shouldComponentUpdate`)
this.forceUpdate();
// set up a promise that will resolve when the component renders
return new Promise((resolve) => {
this.#rendered = resolve;
});
}
render() {
return this.props.children;
}
#rendered = () => {};
componentDidUpdate() {
// resolve the `updateDOM` promise to notify the View Transition API
// that the DOM has been updated
this.#rendered();Related in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.