From 9fe9d95e3604f75217dc4eb007b9172174abd630 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Sun, 31 May 2026 13:29:15 +0200 Subject: [PATCH] feat(hikes): unify below-map view transition into one sliding panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- package.json | 2 +- src/app.css | 48 ++++++++-------------------- src/routes/+layout.svelte | 8 ++--- src/routes/hikes/[slug]/+page.svelte | 22 +++++++++---- 4 files changed, 35 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 21b8d06f..d7f388cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.95.0", + "version": "1.95.1", "private": true, "type": "module", "scripts": { diff --git a/src/app.css b/src/app.css index 2df529f6..d9d1a833 100644 --- a/src/app.css +++ b/src/app.css @@ -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; } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b176c387..bd61ccf3 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -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]'; diff --git a/src/routes/hikes/[slug]/+page.svelte b/src/routes/hikes/[slug]/+page.svelte index 67a13a59..6dfe9c3d 100644 --- a/src/routes/hikes/[slug]/+page.svelte +++ b/src/routes/hikes/[slug]/+page.svelte @@ -415,21 +415,22 @@ + +
{#if hasStages && stages} {/if} {#if track && track.length > 0 && visibleImagePoints.length > 0} -
+
{/if} - -
{#if hike.icon} @@ -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;