Overview
Two preset-level additions on top of the v6.1.0 unified schema. Public shape stays { paths, type?, variant?, options? } — no callsite breaks from v6.1.x. UX for existing showcases is unchanged unless they opt into the new variants/types.
What changed
axis({ type: "y" }) gains two variants
variant: "default"— directional fade-through. Forward (earlier path → later path) is bottom→top: outgoing exits up, incoming rises from below. ~8 px slide, sequenced composition.variant: "non-directional"— direction-agnostic. Incoming always rises from below; outgoing fades in place without translating. Use for bottom-nav tab swaps that aren't a forward/backward pair.
axis({
paths: ["/photos", "/collections", "/create"],
type: "y",
variant: "non-directional",
});hero gets a type axis for chrome handling
type: "static"(default) — incoming page's chrome snaps in while the shared element morphs in place via clip-path inset + uniform scale. Use when the destination chrome should feel like an extension of the list page (e.g. gallery → fullscreen viewer).type: "fade"— both pages cross-fade as whole surfaces while a temporary shared-element clone morphs above them. Use when each side has its own chrome (back button, app bar, meta panel).
hero({ paths: ["/photos", "/photos/*"], type: "fade" });data-hero-aspect-ratio="W/H" for letterboxed heroes
When the hero element is an <img object-contain> (or any element whose visible content occupies a centered sub-rect of its bbox), add data-hero-aspect-ratio so hero tweens the visible content rect rather than the surrounding letterbox. Without the hint hero falls back to the bbox.
<img
data-hero-enter-key={`item-${id}`}
data-hero-aspect-ratio={`${photo.width}/${photo.height}`}
src={photo.src}
className="h-full w-full object-contain"
/>Accepts "W/H" (e.g. "1600/1067") or a precomputed ratio number (e.g. "1.5").
Hero matching promoted to the documented API
data-hero-enter-key (detail side) + data-hero-exit-key (list side) is now the documented matching path. Both must carry the same stable string value — use the item's id, not its index. The legacy single-attribute data-hero-key is still honored as a fallback when no enter/exit pair matched.
Internals
packages/core/transitions/hero/split into strategy providers (static,fade) underprovider/*with a sharedkeys.tsto break the dispatcher ↔ chrome-strategy import cycle.packages/core/transitions/axis/provider/y/split intodirectional.ts+non-directional.ts(was a singley.ts).
Docs
llms/axis.txtandllms/hero.txtrewritten against the new public surface.- Root
llms.txtentries for axis/hero + the hero/zoom troubleshooting block updated to the enter/exit key model with the aspect-ratio hint. - New showcase: Google Photos. Wires the new bits end-to-end —
hero({ type: "fade" })for photo/collection detail,axis({ type: "y", variant: "non-directional" })for the bottom-nav tabs,drillbetween collections, and a new/collagesheet page reached from the Create tool grid. Photo detail usesdata-hero-aspect-ratioagainst probed real dims.
Install
npm install @ssgoi/react@6.2.0
# or @ssgoi/svelte, @ssgoi/vue, @ssgoi/solid, @ssgoi/angular@ssgoi/core@6.2.0 is pulled transitively.
Compatibility
v6.1.x callers compile and run unchanged. The new axis({ type: "y" }) variants and hero({ type }) are additive — existing hero({ paths }) calls keep the previous in-place morph behavior (now formalized as type: "static"). The legacy data-hero-key attribute still works.