feat(visualizer): Phase 15 control-deck rework
Centered tinted MudOverlay (NowPlayingCard chrome) replaces the anchored popover; eight dials become a deterministic three-row LAVA/WAVE layout; lava + waveform lamp toggles drive a genuine per-subsystem draw-skip; scroll/zoom becomes a slider; playful tooltips; green=interactive/light=static.
This commit is contained in:
@@ -1,56 +1,56 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
@using DeepDrftShared.Client.Common
|
||||
|
||||
@* The single controls affordance, placed by an icon anywhere (Phase 12 §3d-revised). Closed state is
|
||||
just the lava-lamp icon; clicking it floats the eight-knob WaveformVisualizerControls panel over the
|
||||
surface. One panel, one popover host, reused on every host (Mix, Cut, Session, NowPlaying card) — the
|
||||
SOLID seam: variance is the per-host anchor (§8e), never a forked popover.
|
||||
@* The single controls affordance, placed by an icon anywhere (Phase 12 §3d-revised, re-primitived
|
||||
Phase 15 §4). Closed state is just the lava-lamp icon; clicking it floats the control panel as a
|
||||
SCREEN-CENTERED, tinted MODAL over the whole surface. One panel, one host, reused on every host (Mix,
|
||||
Cut, Session, NowPlaying) — the SOLID seam.
|
||||
|
||||
Anchoring follows the SharePopover precedent: Fixed so the panel reads the trigger's bounding rect
|
||||
rather than fighting CSS container tricks. AnchorOrigin/TransformOrigin are per-host
|
||||
parameters (§8e) defaulted to bottom-right open-down — the cleanest case (Mix's TopRightAction corner);
|
||||
tight hosts (the NowPlaying card) override to open away from the card body.
|
||||
PRIMITIVE (Phase 15 §4): a centered MudOverlay, NOT an anchored MudPopover. The panel must read as
|
||||
screen-centered regardless of where the lava-lamp icon sits (Mix corner, Cut/Session ambient,
|
||||
NowPlaying corner). An anchored popover positions off the trigger's bounding rect — the wrong model
|
||||
for "centered on the screen." So the icon is just an opener; the overlay hosts the panel in its centre
|
||||
(the overlay is a full-viewport flex container — its content is centered by .waveform-visualizer-control-
|
||||
overlay in the GLOBAL sheet, since the overlay portals out of this subtree). DarkBackground gives the
|
||||
mild modal tint (alpha from the single --deepdrft-modal-scrim-alpha token, §10.5). There is therefore
|
||||
no AnchorOrigin/TransformOrigin: a centered modal has no anchor (Phase 15 drops those parameters).
|
||||
|
||||
The popover owns NO control state and NO JS interop. The hosted WaveformVisualizerControls panel mutates
|
||||
the shared WaveformVisualizerControlState and raises Changed; the visualizer bridge subscribes. This host
|
||||
only toggles open/closed and places the panel — it stays purely presentational. *@
|
||||
KNOB-DRAG SAFETY (Phase 15 §4, highest-risk detail): RadialKnob mounts its own full-viewport
|
||||
position:fixed; z-index:9999 mouse-capture div WHILE dragging (RadialKnob.razor lines 5–9). That capture
|
||||
div sits ABOVE the overlay scrim, so a knob drag's pointer-up lands on the capture div, never the scrim
|
||||
— the overlay's OnClick does not fire mid-drag, so releasing the mouse outside the panel does NOT close
|
||||
the modal. AutoClose is left OFF (the default) and dismissal is via the explicit scrim OnClick only,
|
||||
carrying the SharePopover idiom forward under the new primitive. The panel stops click propagation so a
|
||||
click INSIDE it never bubbles to the scrim's close handler.
|
||||
|
||||
@* Backdrop dismissal mirrors SharePopover: a viewport overlay closes on outside click. AutoClose stays
|
||||
off so a knob drag (which can land pointer-up outside the panel's DOM subtree) does not dismiss. *@
|
||||
<MudOverlay Visible="@_open" OnClick="@Close" />
|
||||
The host owns NO control state and NO JS interop. The hosted WaveformVisualizerControls panel mutates
|
||||
the shared WaveformVisualizerControlState and raises Changed; the visualizer bridge subscribes. This
|
||||
host only toggles open/closed and centers the panel — it stays purely presentational. *@
|
||||
|
||||
@* Activator and popover share this wrapper so MudPopover anchors off the trigger's bounding rect. *@
|
||||
<div>
|
||||
<MudTooltip Text="Visualizer settings">
|
||||
<MudIconButton Icon="@(_open ? DDIcons.LavaLampFilled : DDIcons.LavaLamp)"
|
||||
Size="@IconSize"
|
||||
Color="Color.Secondary"
|
||||
Disabled="@(!RendererInfo.IsInteractive)"
|
||||
OnClick="@Toggle"
|
||||
aria-label="Visualizer settings"
|
||||
aria-expanded="@_open" />
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Visualizer settings">
|
||||
<MudIconButton Icon="@(_open ? DDIcons.LavaLampFilled : DDIcons.LavaLamp)"
|
||||
Size="@IconSize"
|
||||
Color="Color.Secondary"
|
||||
Disabled="@(!RendererInfo.IsInteractive)"
|
||||
OnClick="@Toggle"
|
||||
aria-label="Visualizer settings"
|
||||
aria-expanded="@_open" />
|
||||
</MudTooltip>
|
||||
|
||||
<MudPopover Open="@_open"
|
||||
Fixed="true"
|
||||
AnchorOrigin="@AnchorOrigin"
|
||||
TransformOrigin="@TransformOrigin"
|
||||
Class="waveform-visualizer-control-popover">
|
||||
@* The tinted modal scrim that also HOLDS the panel. DarkBackground = the mild tint; OnClick on the scrim
|
||||
dismisses (knob-drag-safe, see header). The panel is the overlay's centered child; it stops click
|
||||
propagation so an inside click is not a dismissal. Modal so focus/scroll stay on the panel. *@
|
||||
<MudOverlay Visible="@_open"
|
||||
DarkBackground="true"
|
||||
Modal="true"
|
||||
OnClick="@Close"
|
||||
Class="waveform-visualizer-control-overlay">
|
||||
<div class="waveform-visualizer-control-modal" @onclick:stopPropagation="true">
|
||||
<WaveformVisualizerControls PanelChrome="true" />
|
||||
</MudPopover>
|
||||
</div>
|
||||
</div>
|
||||
</MudOverlay>
|
||||
|
||||
@code {
|
||||
/// <summary>
|
||||
/// Where the panel anchors relative to the trigger icon (§8e). Defaults to opening down-from the
|
||||
/// icon's bottom-right — fits Mix's top-right corner and the ambient hosts. Tight hosts (the
|
||||
/// NowPlaying card) override to open away from the card body.
|
||||
/// </summary>
|
||||
[Parameter] public Origin AnchorOrigin { get; set; } = Origin.BottomRight;
|
||||
|
||||
/// <summary>The panel's own corner that pins to <see cref="AnchorOrigin"/> (§8e).</summary>
|
||||
[Parameter] public Origin TransformOrigin { get; set; } = Origin.TopRight;
|
||||
|
||||
/// <summary>Trigger-icon size. Defaults Large to match the Phase 10 Mix lava-lamp button.</summary>
|
||||
[Parameter] public Size IconSize { get; set; } = Size.Large;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user