Skip to content

feat(splash): loading-curtain splash screen + AboutPill reopener + WebGPU gate#178

Open
rulkens wants to merge 12 commits into
mainfrom
worktree-splash-screen-core
Open

feat(splash): loading-curtain splash screen + AboutPill reopener + WebGPU gate#178
rulkens wants to merge 12 commits into
mainfrom
worktree-splash-screen-core

Conversation

@rulkens
Copy link
Copy Markdown
Owner

@rulkens rulkens commented May 20, 2026

Summary

Implements Plan 1 of 2 for the splash screen: a first-paint loading curtain with branded content, two CTAs (Explore + Tour), a top-bar AboutPill reopener, graceful failure handling, and a synchronous WebGPU-unsupported gate that runs before React mounts. Tour is wired to dismiss-as-no-op; the real scripted-tour itinerary lands in Plan 2 behind the same button.

Built per the 2026-05-20 splash-screen grill transcript and the Plan 1 spec (both shipped in #174).

  • useSplash hook owns visibility, readiness gating (engine ready + no fetches in flight + famous-meta loaded), localStorage versioning (skymap.splash.seenVersion), deep-link bypass (#focus= / #poi= / ?tour=), the 8 s "Continue anyway" escape, and dismiss / reopen actions.
  • Splash dialog is purely presentational — translucent backdrop-blurred card centered over a dim overlay, mobile-responsive (stacked CTAs <480 px, solid backdrop on iOS), accessible (role=dialog, focus trap, Esc dismiss, ARIA progressbar), per-error rendering (webgpu-init-failed / catalog-fetch-failed show Reload; famous-meta-failed disables Tour with a tooltip but keeps Explore live).
  • AboutPill sits in the top-bar pill row next to SearchTrigger + AutoRotateToggle, reopens the splash without bumping the seenVersion.
  • Pre-React WebGPU gate in main.tsx — synchronous typeof navigator.gpu check; on unsupported browsers, document.body.innerHTML is swapped to a static "use Chrome or Edge + caniuse link" page and React never mounts.
  • useFamousMeta gains a ready: boolean flag (flips on both success and swallowed-error paths) so the splash gate doesn't deadlock on deployments without famous_meta.json.

The branch is 12 commits split per plan task (Tasks 1–10 + Task 8 fix-up + AboutPill CSS fix). npm run typecheck && npm test && npm run build all green; final review confirmed PR-ready (one out-of-scope follow-up flagged for future polish: an unrelated hasDeepLink .includes||.startsWith redundancy inherited from the plan).

Follow-up: Plan 2 (docs/superpowers/plans/2026-05-20-splash-screen-02-stub-tour.md) wires the Powers-of-Ten stub camera tour to the Tour button. Independent PR; depends only on this one landing.

Test plan

Automated coverage shipped in this branch:

  • tests/unsupportedPage.test.ts — 4 assertions (string shape + WebGPU + Chrome/Edge mention + caniuse link)
  • tests/hooks/useFamousMeta.test.ts — 3 assertions (ready=false initially, flips on success, flips on rejection)
  • tests/utils/url/hasDeepLink.test.ts — 7 assertions (#focus, #poi, ?tour detection; ignores ?debug/?volumes/?anchors)
  • tests/hooks/useSplash.test.ts — 16 assertions (visibility, deep-link skip, version gating, readiness, dismiss/reopen, 8s timer, error mapping)
  • tests/components/Splash/AboutPill.test.ts — 5 assertions (aria-label, click, Enter, hidden aria-hidden behavior)
  • tests/components/Splash/Splash.test.ts — 15 assertions (dialog role, survey links, attribution, CTAs, blocked state, error states, Continue-anyway, focus trap, Esc)
  • Full suite: 1689 / 262 files passing

Manual smoke (please verify in dev server before merging):

  • First visit (localStorage cleared) → splash appears; Explore + Tour disabled initially, enable when load completes
  • Clicking Explore dismisses; refreshing tab does NOT show splash again
  • Direct visit to /#focus=ngc224 does NOT show splash
  • About pill (top-bar) reopens splash; Explore dismisses again
  • Canvas visible through backdrop blur on desktop (cosmos materializes behind during load)
  • Mobile (< 480 px viewport) stacks Explore + Tour vertically; backdrop is solid (no blur)
  • Esc dismisses the splash
  • Tab cycles through survey links → Explore → Tour → loops back
  • Splash version bump (manually set localStorage["skymap.splash.seenVersion"] = "0") → splash re-shows on next visit
  • Tour button currently dismisses like Explore (Plan 2 will replace this — expected for now)

🤖 Generated with Claude Code

rulkens and others added 12 commits May 20, 2026 03:50
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Skips React mount on browsers without navigator.gpu and renders a
static "use Chrome or Edge" page instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Flips true on both success and swallowed-error paths so a missing
famous_meta.json doesn't deadlock downstream gates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Owns visibility, readiness gate, dismiss/reopen, localStorage versioning,
deep-link bypass, and the 8 s Continue-anyway timer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…lash

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…test

The previous Splash component edit changed the body to avoid a getByText
ambiguity between the body and the error message. Revert the copy to the
spec's mandated text ("Drawn in your browser with WebGPU. Built from real
cosmic data…") and narrow the WebGPU-init test to match "/webgpu failed/i"
so the assertion fires only on the error box, not the body mention.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Splash dialog covers the first-paint window with branded content and
two CTAs; AboutPill joins the top-bar pill row as the reopener.
Tour currently dismisses like Explore — wiring of the stub tour
lands in the companion plan.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…adius

`backdrop-filter: var(--blur-card)` is invalid — the token holds a bare
length (12px), not a filter function. Wrap with `blur(...)` so the frosted-glass
effect actually renders. Sibling pills (SearchTrigger, AutoRotateToggle) use
the correct `blur(var(--blur-card))` pattern; AboutPill was an outlier.

`--radius-pill` was never defined in global.css; the project defines
--radius-xs through --radius-2xl, but no pill variant. Sibling pill components
use the literal `999px` for the full-pill effect. Match that here so the
AboutPill renders as a circle, not a square with 0px radius.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
skymap 9e3434d Commit Preview URL

Branch Preview URL
May 20 2026, 02:19 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant