docs(phase-15): record visualizer controls landing

Move Phase 15 from PLAN to COMPLETED; fix DDIcons location to
DeepDrftShared.Client/Common; update WaveformVisualizerControls/Popover/State
descriptions for the three-row modal-overlay rework.
This commit is contained in:
daniel-c-harvey
2026-06-17 14:50:30 -04:00
parent 1fef60a7fb
commit e38678009e
4 changed files with 26 additions and 29 deletions
-22
View File
@@ -239,28 +239,6 @@ Sequenced as **eight waves**; the critical path is `11.A → 11.B → 11.C → 1
---
## Phase 15 — Visualizer Controls Enhancements
A presentation + interaction rework of the **waveform visualizer control surface** — the eight-RadialKnob panel (Phase 12) hosted by `WaveformVisualizerControlPopover`. **Not** a renderer change: the WebGL2 visualizer, the eight continuous dial values + their defaults, and the `Changed`-event bridge seam are all unchanged. This phase reworks how the controls are *reached and presented*, adds **two on/off toggles** (lava, waveform), and gives the panel a **deterministic, sectioned layout** that encodes the visualizer's composition (lava field + waveform ribbon, optionally overlaid). Full design, layout contract, primitive rationale, tooltip copy, acceptance, and wave decomposition: `product-notes/phase-15-visualizer-controls-enhancements.md`.
**Phase number:** 14 (releases consolidation) has now landed on dev; 15 was chosen as the next free number when this phase was drafted alongside Phase 14. See `COMPLETED.md` for the Phase 14 record.
**The load-bearing reframe.** Today the eight knobs read as a flat, equal grid — the user cannot tell which knobs drive the lava vs. the waveform, and neither subsystem can be turned off. The new layout sections the controls by subsystem and the two toggles make "lava only" / "waveform only" first-class. The screen-centering and chrome are polish around that.
**Daniel's five requirements (verbatim intent):** (1) panel look-and-feel follows `NowPlayingCard` — square corners, lighter navy, thin light border; (2) popover becomes **screen-centered + modal-tinted** — use the right MudBlazor overlay primitive, do not fight an anchored popover into the center; (3) deterministic three-row layout — **row 1:** lava toggle, waveform toggle, then (only if both on) collisions knob, then color knob far-right; **row 2 (lava on):** "LAVA:" + Gravity/Heat/two-Fluid knobs; **row 3 (waveform on):** "WAVE:" + scroll/zoom **slider** + width knob far-right; (4) playful, non-technical tooltip per control; (5) knob caption icons go **light**, not accent-green.
**Primitive decision (spec §4): `MudOverlay` (centered, `DarkBackground` tint, modal), not `MudPopover`.** `MudPopover` is by design *anchored* to its trigger — screen-centering means fighting its positioning model (the "do not fight MudBlazor" Daniel called out). `MudOverlay` gives screen-centering + the modal tint with the smallest delta from today's idiom (we already host a `MudOverlay` for dismissal; it graduates from transparent click-catcher to tinted scrim that holds the panel). `MudDialog` is the documented fallback if `MudOverlay` centering fights the knob-drag overlay — escalate, don't hand-roll a fixed-position div. CSS-isolation constraint persists (overlay portals content out of the subtree → panel chrome stays in the **global** `deepdrft-styles.css`, not the scoped `.razor.css`).
**The one renderer-adjacent touch.** The two new toggles back two new `WaveformVisualizerControlState` booleans (`LavaEnabled` / `WaveformEnabled`, both default true). The bridge (`WaveformVisualizer`) must enable/disable the corresponding subsystem in the WebGL module on `Changed` — the one place this phase reaches past pure presentation. **"Off" means fully absent** (resolved 2026-06-17): the subsystem is not drawn, contributes no collisions, incurs no render cost — not dimmed. This is a **real build**, not a flag flip: the implementer should expect the per-subsystem draw-skip seam **does not yet exist** in `WaveformVisualizer.ts` and that building it is part of 15.A (spec §6, §10.1). Budget the renderer touch as a draw-skip path, not a one-line uniform push.
**Colour principle — green = interactive, light = non-interactive** (resolved 2026-06-17). One rule governs every control's colour: interactive elements (the lamp toggles, knob arcs/pointers, scroll slider) are **green-accent**; static/decorative elements (the "LAVA:" / "WAVE:" section labels, knob caption icons) are **light**. This unifies the original requirement 5 (icons light), the section-label colour, and the toggle colour into one principle — apply it uniformly, not per-control (spec §5).
**Sequenced as one wave, four tracks** (small enough to ship as a single bundled PR — recommended, since the tracks are tightly coupled around one component pair and splitting would be churn): **15.A** state booleans + bridge wiring (load-bearing); **15.B** screen-centered tinted-modal primitive + NowPlayingCard chrome; **15.C** deterministic re-layout + toggles + scroll-slider; **15.D** tooltips + light icon colour. Dependency shape: `15.A → {15.B, 15.C} → 15.D`.
**Open questions — all RESOLVED 2026-06-17 (spec §10, kept visible):** (1) "off" means **fully absent** (not drawn, no collisions, no render cost — not dimmed); the per-subsystem draw-skip seam is expected **not** to exist yet and building it is part of 15.A; (2) scroll/zoom binds to **`ScrollSpeed` alone**; (3) "LAVA:"/"WAVE:" labels are **light** (green is reserved for interactive elements); (4) toggles are **iconographic lamp toggles** (lit/unlit), **green** because interactive; (5) tint opacity is **mild** and resolves from a **single token/constant** (one point of change, no repeated magic number). **Post-landing doc-keeper note** (not this phase's work): root `CLAUDE.md` wrongly places `DDIcons.cs` in `DeepDrftPublic.Client.Common` — it lives in `DeepDrftShared.Client/Common`.
---
## Working with this file
- **Add items by extending an existing phase first**; only create a new phase when the addition genuinely doesn't fit any of 15. Phase numbers are organisational, not sequencing.