feat(hikes): unify below-map view transition into one sliding panel

The detail-page enter/exit transition previously slid only the metric
tiles up from the bottom — the wrapper had no background, so its
snapshot was transparent and no containing panel moved. The photo strip
also animated separately, sliding in from the right.

Wrap everything below the hero map (stage nav, photo strip, metrics,
tags, elevation, scroll area, footer) in one `.below-map` element with
`view-transition-name: hike-below-map` and an opaque background, so the
whole sheet — background included — slides up on enter and down on exit
as a single panel. Drop the obsolete hike-strip right-slide rules and
keyframes; rename hike-below-strip → hike-below-map.
This commit is contained in:
2026-05-31 13:29:15 +02:00
parent cd7912fa8f
commit 9fe9d95e36
4 changed files with 35 additions and 45 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "homepage",
"version": "1.95.0",
"version": "1.95.1",
"private": true,
"type": "module",
"scripts": {
+14 -34
View File
@@ -467,10 +467,11 @@ a:focus-visible {
/* ============================================
HIKES TRANSITIONS
Cards + filter fly in/out vertically, clicked card morphs into the hero
map (cross-fade between thumbnail and map), photo strip slides in from
the right. Page chrome under the hero cross-fades so nothing snaps in
at transition end. Lives in app.css (not the page component) so the
rules are still loaded on the OLD side of a nav AWAY from /hikes.
map (cross-fade between thumbnail and map), and the whole below-map panel
(an opaque sheet) slides up from the bottom. Page chrome under the hero
cross-fades so nothing snaps in at transition end. Lives in app.css (not
the page component) so the rules are still loaded on the OLD side of a
nav AWAY from /hikes.
============================================ */
@keyframes hikes-fly-up {
@@ -489,15 +490,6 @@ a:focus-visible {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes hike-strip-in-right {
from { transform: translateX(100vw); }
to { transform: translateX(0); }
}
@keyframes hike-strip-out-right {
from { transform: translateX(0); }
to { transform: translateX(100vw); }
}
/* Only-child hike-fly-in pseudos (unpaired cards/filter on enter or exit):
* kill UA's default fade, switch blend mode so the custom fly animation
* shows clean motion against the rest of the page. */
@@ -533,29 +525,17 @@ html.vt-exit-hikes::view-transition-old(.hike-fly-in):only-child {
animation: hikes-fly-down 700ms cubic-bezier(0.4, 0.1, 0.4, 1) both;
}
/* Photo strip slides in from the right when arriving at a detail page,
* and slides back out whenever the detail page is left for any other
* route (back to /hikes, off to /, /hikes/route-builder, …). Both exit
* scopes (vt-enter-hikes for the back-nav case, vt-exit-hike-detail for
* everywhere else) trigger the same animation. */
html.vt-enter-hike-detail::view-transition-new(hike-strip):only-child {
animation: hike-strip-in-right 600ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
html.vt-enter-hikes::view-transition-old(hike-strip):only-child,
html.vt-exit-hike-detail::view-transition-old(hike-strip):only-child {
animation: hike-strip-out-right 600ms cubic-bezier(0.4, 0.1, 0.4, 1) both;
}
/* Everything below the photo strip on a detail page (metrics, tags,
* elevation chart, scroll area, meta footer) slides up from the bottom
* on enter and back down on any exit. Wrapper element carries
* `view-transition-name: hike-below-strip`; the rest of the page chrome
* still cross-fades via the root-pseudo rule above. */
html.vt-enter-hike-detail::view-transition-new(hike-below-strip):only-child {
/* Everything below the hero map on a detail page — stage nav, photo strip,
* metrics, tags, elevation chart, scroll area, meta footer — slides up from
* the bottom on enter and back down on any exit, as one panel. The wrapper
* carries `view-transition-name: hike-below-map` and an opaque background, so
* the whole sheet (background included) moves; the hero map morphs separately
* above, and the rest of the page chrome cross-fades via the root-pseudo rule. */
html.vt-enter-hike-detail::view-transition-new(hike-below-map):only-child {
animation: hikes-fly-up 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
html.vt-enter-hikes::view-transition-old(hike-below-strip):only-child,
html.vt-exit-hike-detail::view-transition-old(hike-below-strip):only-child {
html.vt-enter-hikes::view-transition-old(hike-below-map):only-child,
html.vt-exit-hike-detail::view-transition-old(hike-below-map):only-child {
animation: hikes-fly-down 700ms cubic-bezier(0.4, 0.1, 0.4, 1) both;
}
+4 -4
View File
@@ -80,10 +80,10 @@
// card pairs into the hero and the rest fly out.)
// - vt-enter-hike-detail: arriving at a hike detail page (card → zoom).
// - vt-exit-hike-detail: leaving a hike detail page for anywhere
// else (back to /hikes, off to /, route-builder, …) → photo strip
// slides back out to the right and the below-strip block flies
// down. Excluded for slug → slug navigations (both sides share the
// same route.id, so paired UA transitions handle them).
// else (back to /hikes, off to /, route-builder, …) → the whole
// below-map panel flies back down off the bottom. Excluded for
// slug → slug navigations (both sides share the same route.id, so
// paired UA transitions handle them).
const intoHikesIndex = toId === '/hikes' && fromId !== '/hikes';
const outOfHikesIndex = fromId === '/hikes' && toId !== '/hikes';
const intoHikeDetail = toId === '/hikes/[slug]';
+16 -6
View File
@@ -415,21 +415,22 @@
</div>
</section>
<!-- Everything below the hero map — stage nav, photo strip, metrics,
tags, elevation chart, scroll area, footer — is wrapped in one panel
so view-transitions slide the whole block (with its own background)
up from the bottom on enter and down on exit. The hero map morphs
separately above this. -->
<div class="below-map" style="view-transition-name: hike-below-map">
{#if hasStages && stages}
<HikeStageNav {stages} />
{/if}
{#if track && track.length > 0 && visibleImagePoints.length > 0}
<section class="strip-area" style="view-transition-name: hike-strip">
<section class="strip-area">
<HikePhotoStrip images={visibleImagePoints} {track} {stages} />
</section>
{/if}
<!-- Everything below the photo strip is wrapped so view-transitions
can slide the whole block (metrics, tags, elevation chart, scroll
area, footer) up from the bottom on enter and down on exit. The
hero map and strip animate separately above this. -->
<div class="below-strip" style="view-transition-name: hike-below-strip">
<section class="metrics" aria-label="Tourendaten">
{#if hike.icon}
<img class="route-icon" src={hike.icon} alt="" aria-hidden="true" />
@@ -985,6 +986,15 @@
opacity: 0.55;
}
/* The whole below-the-map block. The solid background makes its
view-transition snapshot an opaque panel, so on enter/exit the entire
sheet (background included) slides up/down from the bottom rather than
just the metric tiles appearing to float. */
.below-map {
position: relative;
background: var(--color-bg-primary);
}
.strip-area {
padding-inline: 1rem;
margin-top: 0.5rem;