hero
Hero preserves the identity of matching elements across two pages while the surrounding surfaces change.
Drill-in — List → detail, going one level deeper.
When this motion fits
- When to use
- Use it when a thumbnail, avatar, or other stable entity appears on both pages and should visibly continue.
- What moves
- Each matched element morphs from its source bounds into its destination bounds; multiple distinct pairs can move together.
- Avoid when
- Avoid it when there is no stable shared identity. If one card should open into the whole page, Zoom is usually clearer.
Add it to a route rule
hero() sets the motion; the rule around it decides which navigations get it. The config shape is the same in every framework.
import { hero } from "@ssgoi/react/view-transitions";
const config = {
transitions: [
{
from: "/list",
to: "/detail/*",
transition: hero(),
},
],
};Pattern forms, priority and the scroll defaults that come with each rule shape are on Route rules.
Connect the source to the destination
The attribute value is the element's stable identity. Source and destination values must match exactly.
| Page | Attribute on the element |
|---|---|
| Source page | data-hero-exit-key="same-id" |
| Destination page | data-hero-enter-key="same-id" |
- You may mark multiple distinct key pairs; Hero animates every pair it can match.
- Keep each identity unique on a page. If a key is duplicated, the first element in DOM order is used.
- Pairs without a matching key on the other page are skipped.
{/* Source: list or collapsed page */}
<img
data-hero-exit-key={item.id}
src={item.thumbnail}
alt={item.alt}
/>
{/* Destination: detail or expanded page */}
<img
data-hero-enter-key={item.id}
src={item.full}
alt={item.alt}
/>Configurations
type, variant and option are independent. Each clip is recorded from a demo published on ssgoi.dev. Combinations without a published demo keep the API details without a substitute clip.
static · default
type: staticvariant: defaultdefaultThe surrounding pages switch without a surface fade while the shared element continues between them.
hero({ type: "static" })fade · default
type: fadevariant: defaultThe surrounding pages fade as the shared element continues, softening the hand-off.

hero({ type: "fade" })Open live demoOpens at the source screen
static · smooth
type: staticvariant: smoothSmooth changes the shared element's interpolation for a softer, more continuous morph. It is independent of the static/fade type.

hero({ type: "static", variant: "smooth" })Open live demoOpens at the source screen
fade · smooth
type: fadevariant: smoothCombines the smooth shared-element interpolation with a fading page hand-off.
hero({ type: "fade", variant: "smooth" })
Agent guide: /llms/transitions/hero.txt — every prop, the required markup, and a config fragment as plain text.