feat(splash): film-title redesign + WebGPU gate + shared Button/PillButton primitives#178
Merged
Conversation
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>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
skymap | b7d0d05 | Commit Preview URL Branch Preview URL |
May 28 2026, 10:56 PM |
Cascades to title / body / CTAs / footer via inheritance. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…n-core # Conflicts: # src/@types/engine/UseFamousMetaReturn.d.ts # src/components/App/App.tsx # src/hooks/useFamousMeta.ts
…ic fallback Synthetic is the "no real data, show *something*" path — at the bulk-survey defaults (floor 0.02 / falloff 1000 Mpc) the 1000-Mpc cloud attenuated to a near-black haze, defeating the fallback's reason for existing. Bump to Milliquas-style values (floor 0.15 / no depth fade) so the user sees a visible cosmos in worktrees / dev environments without .bin data. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
NaN positionAngleDeg propagates through the vertex shader's cos/sin and
the fragment's r² ellipse-mask test. Per IEEE 754, all NaN comparisons
return false, so the `if (r2 > 1.0) { discard; }` silently skips for
every fragment. The full quad rasterises and the `rgb * alpha = NaN *
NaN = NaN` output renders as a black square.
The shader DOES guard axisRatio against NaN (`select(1.0, ..., absAR >
0.0)`), but the PA path doesn't. Real catalogs never trip this because
the offline pipeline fills missing PA via `fallbackOrientation`;
synthetic is the only source generated at runtime, and the latent bug
sat undiscovered because synthetic was so dim from the now-fixed
intensity floor that the black squares weren't separately visible.
Fix the symptom at the data source — emit `axisRatio=1.0` and `PA=0`
(matches the original "render as a round point" intent without the NaN
trap). The shader could also gain a NaN guard for PA; deferring that
until a second source actually needs it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Splash:
- Drop the centred card. Bottom-left typographic overlay with localised
vignette; centre stays clear for the Milky Way + "You are here" marker.
- Cormorant Garamond title via Google Fonts (matches the in-scene MSDF
label face). Staggered fade-up reveal, accent draw-underline beat.
- New SplashProgress at viewport edge replaces the inline card progress
row. Bytes-based count; indeterminate sweep when totalBytes unknown.
- Click on the backdrop dismisses, matching Esc → onExplore.
- New copy ("Have a look at the neighbours") with catalogue credits in
the footer rather than the body.
Shared chrome:
- New common/Button primitive. font:inherit so it speaks whatever the
parent speaks; variants primary/secondary/ghost. SettingsPanel reset
+ SpaceMouse connect adopt it.
- New common/PillButton primitive for the top-bar icon pills. AboutPill
+ AutoRotateToggle refactored to thin semantic wrappers over it, so
the two pills are now visually identical by construction.
- PlayIcon, PauseIcon, InfoIcon extracted to their own files.
Skill:
- .claude/skills/create-component/ encodes the project's component
conventions (.root class, default-export form, one-component-per-file,
no global CSS, default-no-tests).
Test deletions: Splash, AboutPill, AutoRotateToggle tests removed in
favour of behaviour-only coverage; thin presentational wrappers don't
warrant test files per the new skill's guidance.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 tasks
rulkens
added a commit
that referenced
this pull request
May 28, 2026
Plan 01 (loading curtain + AboutPill + useSplash + WebGPU gate) shipped in PR #178 plus the in-session film-title redesign. Move its plan file under completed/ and drop the BACKLOG line. Plan 02 (stub tour) is left in the active queue; Tour CTA currently dismisses without running. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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).
useSplashhook 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.Splashdialog 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-failedshow Reload;famous-meta-faileddisables Tour with a tooltip but keeps Explore live).AboutPillsits in the top-bar pill row next to SearchTrigger + AutoRotateToggle, reopens the splash without bumping the seenVersion.main.tsx— synchronoustypeof navigator.gpucheck; on unsupported browsers,document.body.innerHTMLis swapped to a static "use Chrome or Edge + caniuse link" page and React never mounts.useFamousMetagains aready: booleanflag (flips on both success and swallowed-error paths) so the splash gate doesn't deadlock on deployments withoutfamous_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 buildall green; final review confirmed PR-ready (one out-of-scope follow-up flagged for future polish: an unrelatedhasDeepLink.includes||.startsWithredundancy 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)Manual smoke (please verify in dev server before merging):
/#focus=ngc224does NOT show splashlocalStorage["skymap.splash.seenVersion"] = "0") → splash re-shows on next visit🤖 Generated with Claude Code