From ba6b47832084c9252d0d25fe0bfccb65b143713a Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Mon, 5 Oct 2026 09:27:30 -0400 Subject: [PATCH] nook: collapse changelog history into a fixed-height scroller A long appcast made the page grow with every release and pushed historical versions far below the fold. Versions now collapse to a header row inside a fixed-height vertical panel (max-h 70vh): expanding one never shifts the page, and history is browsed by scrolling inside it. The newest release starts open; notes stay mounted and toggle via hidden rather than unmounting, so crawlers still see every entry. Tests: vinxi build clean; tsc clean. Issue: FRE-13 --- src/routes/nook/changelog.tsx | 46 +++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/routes/nook/changelog.tsx b/src/routes/nook/changelog.tsx index 4dd4867..9ee190e 100644 --- a/src/routes/nook/changelog.tsx +++ b/src/routes/nook/changelog.tsx @@ -5,8 +5,13 @@ * launch, so this page renders exactly what Sparkle publishes: one source * of truth, no second place to write release notes. Doubles as the raw * material for the release-announcement job (marketing/README.md). + * + * Layout: the version list lives in a fixed-height vertical scroller, so + * expanding a release never shifts the page — history is browsed inside + * the panel. Rows collapse to their header; notes stay in the DOM + * (visibility toggled, not unmounted) so crawlers still see every entry. */ -import { For, Show } from "solid-js"; +import { For, Show, createSignal } from "solid-js"; import { query, createAsync } from "@solidjs/router"; import { PageHead } from "~/components/PageHead"; import { EdgeCacheHeaders } from "~/components/EdgeCacheHeaders"; @@ -20,6 +25,11 @@ const getReleases = query(async () => { export default function NookChangelogPage() { const releases = createAsync(() => getReleases()); + // Newest release starts open; every other row starts collapsed. + const [openVersion, setOpenVersion] = createSignal(null); + + const isOpen = (version: string, index: number) => + openVersion() === null ? index === 0 : openVersion() === version; return ( <> @@ -47,12 +57,24 @@ export default function NookChangelogPage() {

} > -
+
- {(release) => ( -
-
-

+ {(release, i) => ( +
+

+ {/* Notes are the publisher's own HTML, written to the same - S3 appcast the Sparkle updater consumes. */} + S3 appcast the Sparkle updater consumes. Kept mounted + and toggled via `hidden` so the content stays crawlable. */}