fix(docs): keep SPA transitions via astro-vtbot so search survives nav - #309
Conversation
Starlight's built-in search broke after the first in-page navigation: the search box vanished and the console showed `InvalidStateError: Failed to execute 'showModal' on 'HTMLDialogElement': The element is not in a Document`. Root cause: Head.astro added a bare `<ClientRouter/>` (#142), which Starlight does not support out of the box — the lead maintainer warns it breaks search and the mobile menu (withastro/starlight#2823), and it's unchanged on Starlight main. The SPA router swaps the header on every navigation, leaving the previous page's window `keydown` listener pointing at a detached `<dialog>` (showModal throws) and never re-initializing Pagefind (gated on a one-shot `DOMContentLoaded`), so the modal renders empty. The mobile menu broke the same way. Fix: drop `<ClientRouter/>` and use browser-native cross-document view transitions (`@view-transition { navigation: auto }` in global.css). Real navigations mean Starlight's search and mobile menu work unmodified. - Remove the now-inert `astro:page-load` / `astro:after-swap` listeners across the components; each already inits on `DOMContentLoaded`, so behavior is unchanged under full-page navigation. - Guard the View-Transitions-spec "Transition was skipped" rejection (graceful skip on slow loads) so it stays out of the console / error tracking. Verified on a production build (astro build + worker) with Playwright: search populates after navigation with no showModal error; mobile menu toggles after navigation; native VT activates and skip-rejections stay silent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 26 minutes and 44 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR fixes docs search and mobile menu state loss during in-page navigation by adopting the astro-vtbot integration for Starlight. The dependency is added to ChangesDocs Search and Mobile Menu Navigation Fix
🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📚 Docs preview is live → https://548f6b8d-wavehouse-docs.wave-rf.workers.dev
|
…es nav Supersedes the cross-document-VT approach in f1079ec. The design-token rebuild (#142) put a bare <ClientRouter/> in Head.astro, which Starlight does not support: the SPA router swapped the whole header on every navigation, so the prior page's window ⌘K handler pointed at a now-detached <dialog> (InvalidStateError on showModal), and Pagefind's one-shot DOMContentLoaded init never re-ran — search broke, and the mobile menu with it (withastro/starlight#2823). Rather than drop the SPA model (instant nav, preserved sidebar scroll) for browser-native cross-document transitions, adopt astro-vtbot's Starlight integration — the supported path #2823 names. Head.astro wraps Starlight's Head in astro-vtbot/components/starlight/Base.astro, which supplies <ClientRouter fallback="swap"/> plus: - <ReplacementSwap/> — swaps only the main content frame and preserves the rest of the header, so the search <dialog> and its ⌘K listener are never detached. - <StarlightConnector/> — re-runs Starlight's per-nav init: closes the mobile menu, updates the current-page marker, and keeps the existing sidebar DOM when its links match (preserving scroll position). The docs components keep the astro:page-load / astro:after-swap re-init they have on main (navigations are still Astro View Transitions), so nothing else changes. Verified on a production build (astro build + Cloudflare Worker) with Playwright: SPA nav preserves the JS context (no full reload); ⌘K search opens and returns results after nav with no showModal error and one <dialog>; the mobile menu opens, auto-closes on nav, then re-opens. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The CHANGELOG entry carries the full rationale; keep the inline comment concise (pre-push review [MAY] + AGENTS.md craftsmanship). Comment-only — the two inline scripts are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@coderabbitai review Heads up: this PR was reframed since your last (rate-limited) pass — it now swaps the bare |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
# Get PR details and diff
gh pr view 309 --repo Wave-RF/WaveHouse
echo "=== PR FILES CHANGED ==="
gh pr diff 309 --repo Wave-RF/WaveHouseLength of output: 24546 🏁 Script executed: #!/bin/bash
set -e
# Read key files
echo "=== docs/src/components/Head.astro ==="
cat docs/src/components/Head.astro
echo ""
echo "=== docs/package.json ==="
cat docs/package.json
echo ""
echo "=== CHANGELOG.md ==="
cat CHANGELOG.mdLength of output: 208884
Review of PR
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 77ee70f2-592c-4a3f-97ce-cdfb756a61d6
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
CHANGELOG.mddocs/package.jsondocs/src/components/Head.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: CI
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx,json,md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Biome owns JavaScript/TypeScript/JSON linting and formatting; markdownlint owns Markdown style; misspell owns spelling — all under
make lint/make fix; accuracy/clarity/doc-sync is reviewed separately by docs-reviewer
Files:
docs/package.jsonCHANGELOG.md
{clients/ts/**/*,tests/e2e/sdk/**/*,docs/**/*}
📄 CodeRabbit inference engine (AGENTS.md)
Use pnpm (≥ 11.1) + Node 22 LTS (
.nvmrc) for JavaScript/TypeScript;make toolsruns one rootpnpm install --frozen-lockfileacross three workspaces (SDKclients/ts/, E2Etests/e2e/sdk/, docsdocs/)
Files:
docs/package.jsondocs/src/components/Head.astro
🔇 Additional comments (5)
docs/src/components/Head.astro (4)
1-17: LGTM!Also applies to: 119-119
28-70: LGTM!
84-118: LGTM!
18-27: LGTM!CHANGELOG.md (1)
23-23: LGTM!
astro-vtbot is a build-time Astro/Starlight integration like @astrojs/starlight and the starlight-* plugins (all in `dependencies`); `devDependencies` here is genuine tooling (playwright, wrangler, workers-types). Aligns the grouping. Addresses the CodeRabbit review on #309. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#313) ## What A broad polish pass over the docs site, building on #309's astro-vtbot SPA integration — evolved across several overnight cycles from PR-preview feedback. (The direction-aware page slides + title morph from round 1 were tried and **ripped out** on review — too much motion for docs.) ### Progress feedback - **Navigation progress bar** — thin accent bar on slow loads (grace delay keeps fast navs clean). Self-hosted on vtbot's `loading()` hook: vtbot's own `<ProgressBar/>` imports Swup's plugin **from unpkg.com at runtime in every visitor's browser** (verified in the built bundle), which fails our supply-chain bar. - **Reading-progress bar** (`ReadingProgress.astro`) — a 2px accent line under the header filling with how far through the article you've scrolled; spans only the content column, hidden ≥72rem where the right-rail TOC takes over. The mobile answer to "where am I on this page". - Hover **prefetch** verified already active via ClientRouter (no change needed); reduced-motion guard zeroes all view-transition animations. ### Starlight chrome - **Search dialog branded** (three rounds) — design-system frame + pop, blurred backdrop, code-surface input, card result groups with header band + surface-tint row hover, thin branded scrollbars (dialog frame scroller included), accent `<mark>` hits, branded clear/load-more controls. - **Asides on brand hues** — and then *used*: nineteen titled note-blockquotes across api/pipes/access-control/sdk/development became real `:::note`/`:::caution` asides (sharp edges → caution, clarifications → note). - **Tabs as a segmented control**, prose `kbd`/`mark`, accent anchor hover, inner-surface scrollbars, mobile menu button kept on the surface scale, h2 section rule fades out instead of boxing each section. ### Landing page - New **SDK showcase** — "Query it like a database. Subscribe to it like a socket." with Ingest / Query / Live-updates tabs, every snippet type-checked against `clients/ts/src` by reviewers. This surfaced a **latent bug in sdk.md's Live Queries example** (chained `.where()` off `from()`, which has no builder methods) — fixed in both places. - The orphan "How it ships" card folded into the quickstart prose. ### Docs IA + content - Sidebar gains a **Reference** group (API Reference, TypeScript SDK) — lookup vs narrative; no URL changes. - **Getting Started → "Troubleshooting first runs"**: the five first-session trip-ups (schema-refresh 404, pre-flush empty query, fail-closed 403 on non-demo tables, port conflicts, cold-start timing), every claim verified against server code + compose by both reviewers. ### 404 — "signal lost" Landing atmosphere, mono 404, an **EKG trace** (heartbeat decaying to flatline, redrawn by a looping monitor-sweep over a live→dead gradient, dim static ghost underneath, blinking sample dot; static for reduced motion), card quick links, exactly one accessible heading. ### PostHog - SPA pageview setup verified correct as-is (`history_change` + init sentinel); added `capture_exceptions: true` for error tracking on docs JS. ## Verification - Playwright against the production build each cycle: search survives SPA navs, reading bar 0→0.53→1.0 through a long article @390px and re-arms after navigation, progress bar under throttled fetch, 404 single-heading, hover-prefetch live, no console errors. - Screenshot corpus across 390/768/1440/1920/2560px × dark/light incl. search/mobile-nav open; wide-viewport per-element overflow check (1920+2560) clean. - Lighthouse (local, prod build): **95 perf / 100 a11y / 100 best-practices / 92 SEO**, CLS 0.039, LCP intact. - `make ci` green + both pre-push reviewers `ship_it` on every push (9 review rounds; 2 iterate rounds caught real bugs — the sdk.md live-query defect and two aside-conversion artifacts — both fixed). Deliberately *not* done: splitting api.md/sdk.md (URL churn + redirects felt wrong to ship overnight without feedback — happy to do as a follow-up), Steps adoption on getting-started (would drop the numbered sections from the TOC). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Problem
On the live docs site, Starlight's built-in search breaks after the first in-page navigation — the search box disappears and the console shows:
The mobile menu breaks the same way. Root cause: the design-token rebuild (#142) added a bare
<ClientRouter/>(Astro View Transitions) toHead.astro. Starlight does not support a bare<ClientRouter/>— its lead maintainer warns it breaks search and the mobile menu (withastro/starlight#2823). The SPA router swaps the whole header on every navigation, which:window⌘K listener pointing at a now-detached<dialog>→ the next ⌘K callsshowModal()on an element no longer in the document →InvalidStateError.DOMContentLoaded) → after the first search the box reopens empty.Approach (revised)
Keep the SPA model and fix search the supported way: the
astro-vtbotStarlight integration that #2823 points to.Head.astronow wraps Starlight'sHeadinastro-vtbot/components/starlight/Base.astro, which supplies:<ClientRouter fallback="swap"/>— the same SPA transitions as before (instant nav, no full-page flash).<ReplacementSwap/>— swaps only the main content frame and preserves the rest of the header, so the search<dialog>and its ⌘K listener are never detached. This is the precise fix for theshowModalcrash.<StarlightConnector/>— re-runs Starlight's own per-navigation init: closes the mobile menu, updates the current-page marker, and keeps the existing sidebar DOM when its links are unchanged (preserving scroll position).Net change vs
mainis four files:Head.astro(the wrapper),docs/package.json+pnpm-lock.yaml(theastro-vtbotdevDep), and aCHANGELOG.mdentry. The other docs components keep theastro:page-load/astro:after-swapre-init they already have onmain— navigations are still Astro View Transitions, so nothing else changes. (Head.astro's large line count is mostly re-indentation from wrapping the existing head content; the two inline<script>blocks are byte-unchanged frommain—git diff -wconfirms.)Trade-off
Adds the
astro-vtbotdependency — single-maintainer, but the de-facto Astro View Transitions library and the path the Starlight project itself points to in #2823. Astro 6 compatible (the package builds against Astro 6 and declares no peer-dep constraints).Verification
Driven with Playwright against a production build (
astro build+ the Cloudflare Worker), not dev:showModalerror, and exactly one<dialog>in the document.make cigreen;astro checkclean.🤖 Generated with Claude Code