docs(welcome): brainstorming spec for the Welcome screen + controls
Unify #loading / #motion-warning / #run-sim into one #welcome overlay: heads-up notice + four output controls (Video on, Reduce motion off, Audio 2, English) + Loading Universe progress. Two states (welcome → centered loading); right panel hidden until entry; Continue is the single entry gesture. Forward note: extra welcome copy lands later. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
# Welcome screen — design
|
||||
|
||||
**Date:** 2026-06-30
|
||||
**Status:** Approved (brainstorming)
|
||||
**Surface:** `simulator/static/` (frontend only — `index.html`, `style.css`, `app.js`, `i18n.js`)
|
||||
|
||||
## Summary
|
||||
|
||||
Replace the current bare boot flow with a single **Welcome screen**: the
|
||||
universal entry gate the visitor sees on every load. It carries the
|
||||
photosensitivity "Heads up" notice, the four output controls (Video, Reduce
|
||||
motion, Audio, Language) with welcome-appropriate defaults, a **Continue**
|
||||
button, and the "Loading Universe" progress. The right control panel is hidden
|
||||
until the visitor enters the simulation.
|
||||
|
||||
## Why
|
||||
|
||||
Today the universe loads behind a bare "Loading Universe" splash; the splash
|
||||
fades to reveal a "Run simulation" button over the black stage; a first-visit
|
||||
"Heads up" modal appears; clicking through begins the experience. The four
|
||||
output controls live in the right panel and are visible the whole time —
|
||||
including during loading, which the panel should not be.
|
||||
|
||||
We want a deliberate, configurable front door: the visitor reads the heads-up,
|
||||
sets their preferences, and presses one button to begin — while the universe
|
||||
loads in the background so entry is instant when they are ready.
|
||||
|
||||
## Current flow (being replaced)
|
||||
|
||||
- `#loading` — fullscreen splash (`Loading Universe` title + `#loading-fill`
|
||||
progress bar). `simulator/static/index.html:10-15`.
|
||||
- `#run-sim` — "Run simulation" button revealed over the black stage after
|
||||
phase-1 preload. `index.html:33`; wired at `app.js:1533`.
|
||||
- `#motion-warning` — first-visit-only "Heads up" modal, persisted dismissed via
|
||||
`WARN_KEY`. `index.html:34-40`; shown by `maybeShowMotionWarning()`
|
||||
(`app.js:1161`).
|
||||
- Four controls in `.panel` (`#visual`, `#audio`, `#reduce-motion`,
|
||||
`#lang-select`). `index.html:46-65`. The panel is visible throughout.
|
||||
- `beginExperience()` (`app.js:1505`) snaps Video on and Audio to
|
||||
`START_AUDIO_LEVEL = "2"` in the click gesture (Safari audio-unlock).
|
||||
|
||||
## Target design
|
||||
|
||||
### 1. One unified `#welcome` overlay
|
||||
|
||||
Fold `#loading`, `#motion-warning`, and `#run-sim` into a single fullscreen
|
||||
`#welcome` overlay layered above everything. It absorbs all three roles. The
|
||||
right `.panel` is **hidden** for the entire welcome + loading period and revealed
|
||||
only on entry to the simulation.
|
||||
|
||||
The overlay contains three blocks:
|
||||
|
||||
1. **Welcome messaging** — the "Heads up — motion & flashing" title + body
|
||||
(today's `warn.*` strings, reworded to point at the on-screen Reduce-motion
|
||||
control rather than "the panel"). Structured so additional welcome copy can be
|
||||
added later (see Forward notes).
|
||||
2. **Controls** — the four output controls (below).
|
||||
3. **Loading** — the "Loading Universe" title + progress bar.
|
||||
|
||||
### 2. Two visual states
|
||||
|
||||
**State A — Welcome (on load):** welcome messaging + controls + Continue button
|
||||
shown; the Loading block sits at the **bottom**, its bar filling as phase-1
|
||||
preload runs in the background.
|
||||
|
||||
**State B — Loading (after Continue, only if not yet loaded):** the welcome
|
||||
messaging and Continue button **disappear**; the **controls remain**; the Loading
|
||||
block moves to **center**. When phase-1 preload completes, auto-enter the
|
||||
simulation.
|
||||
|
||||
**Continue when already loaded** → skip State B; enter the simulation directly.
|
||||
|
||||
State is driven by a class on `#welcome` (e.g. `.welcoming` → `.loading`), with
|
||||
the "loaded yet?" decision made from a flag set when phase-1 preload resolves.
|
||||
|
||||
### 3. Control defaults (welcome screen)
|
||||
|
||||
| Control | Welcome default | Notes |
|
||||
|---------------|-----------------|--------------------------------------------------|
|
||||
| Video | **ON** | Was OFF in the panel; on by default here. |
|
||||
| Reduce motion | **OFF** | Unless OS `prefers-reduced-motion` / stored pref.|
|
||||
| Audio | **2** (0–10) | Was 0 in the panel. |
|
||||
| Language | **English** | Global; changing it re-renders all welcome text. |
|
||||
|
||||
Reduce motion keeps deferring to a stored value / the OS media query when those
|
||||
exist (same precedence as `initReduceMotion()` today); "OFF" is the no-signal
|
||||
default.
|
||||
|
||||
### 4. Entry into the simulation
|
||||
|
||||
Continue is the user gesture that unlocks audio (the role `#run-sim` had). On
|
||||
Continue → enter (either immediately when loaded, or at end of State B):
|
||||
|
||||
1. Copy the four welcome values into the existing panel inputs (`#visual`,
|
||||
`#reduce-motion`, `#audio`, `#lang-select`).
|
||||
2. Fire the existing handlers / `beginExperience()` so the experience starts in
|
||||
the same code paths as today.
|
||||
3. Remove the `#welcome` overlay and reveal `.panel`.
|
||||
|
||||
Per decisions: the four controls **stay in the panel** for mid-experience
|
||||
adjustment; **Video-off at entry** starts with video off (audio still plays per
|
||||
the Audio level — `beginExperience` no longer forces Video on regardless).
|
||||
|
||||
### 5. Controls drive shared state
|
||||
|
||||
The welcome controls write the same underlying state as the panel controls — they
|
||||
are not a parallel system:
|
||||
|
||||
- **Language** routes through the global `setLanguage()`, which sets `activeLang`
|
||||
and runs `applyUiStrings()` over **all** `[data-i18n]` elements — so the
|
||||
heads-up copy, control labels, and Continue button re-render live, exactly like
|
||||
the panel selector does today. The panel `#lang-select` value is synced to
|
||||
`activeLang` on entry.
|
||||
- **Reduce motion** sets the same `reduceMotion` variable + `RM_KEY` localStorage
|
||||
and calls `applyReduceMotion()`; panel checkbox synced on entry.
|
||||
- **Audio / Video** values are applied on entry via the panel inputs +
|
||||
`beginExperience()`.
|
||||
|
||||
### 6. Behavior changes (intentional)
|
||||
|
||||
- The welcome screen shows on **every** load (it is the entry gate holding the
|
||||
controls), so the first-visit-only persistence of the heads-up (`WARN_KEY`) is
|
||||
**retired**.
|
||||
- Entry uses the **chosen** Audio level rather than always snapping to 2 (2 is the
|
||||
default, not a forced value).
|
||||
- `#run-sim` is removed; **Continue** is the single entry button.
|
||||
|
||||
## i18n
|
||||
|
||||
New / changed `UI_STRINGS` keys in `simulator/static/i18n.js` (all four langs —
|
||||
en/es/fr/ja, matching existing parity):
|
||||
|
||||
- A Continue button label (reuse `warn.continue` if suitable, or add
|
||||
`welcome.continue`).
|
||||
- Reworded `warn.body` (point at the on-screen Reduce-motion control).
|
||||
- Welcome-screen control labels reuse the existing `output.video`,
|
||||
`output.audio`, `rm.label` keys (already translated). The language selector
|
||||
needs no string (native names from the registry).
|
||||
|
||||
All welcome text must live under `data-i18n` so `applyUiStrings()` re-renders it
|
||||
on language change.
|
||||
|
||||
## Out of scope / Forward notes
|
||||
|
||||
- **Additional welcome copy** beyond the heads-up (intro / framing text) comes in
|
||||
a later pass, once this flow works. The welcome-messaging block is structured so
|
||||
adding more `data-i18n` paragraphs is trivial.
|
||||
- No backend / API changes. No content-pipeline changes.
|
||||
|
||||
## Testing
|
||||
|
||||
Frontend lives behind Playwright e2e (`simulator/static/` tests) + node unit
|
||||
tests. Plan to:
|
||||
|
||||
- **Update** existing tests that reference `#loading`, `#run-sim`, and
|
||||
`#motion-warning` to the new `#welcome` flow.
|
||||
- **Add** coverage for:
|
||||
- Welcome defaults (Video on, Reduce motion off, Audio 2, English).
|
||||
- Language switch re-renders welcome text (heads-up + labels + Continue) live.
|
||||
- Continue **while loading** → State B (messaging gone, controls remain,
|
||||
progress centered), then auto-enter when loaded.
|
||||
- Continue **when already loaded** → straight into the simulation.
|
||||
- `.panel` hidden during welcome + loading; revealed on entry.
|
||||
- Welcome control values carry into the panel inputs on entry.
|
||||
|
||||
Environment caveats (from prior sessions): this box has only `python3` (start
|
||||
uvicorn by hand; `reuseExistingServer`); a stale uvicorn is the recurring
|
||||
"no transitions" root cause; `loop-recovery.spec.ts` fails on a clean baseline
|
||||
here (boots without video).
|
||||
Reference in New Issue
Block a user