docs: resolve four Phase 17 open questions (OQ1/OQ4/OQ8/OQ10), defer ReleaseGallery card affordance
This commit is contained in:
@@ -1,8 +1,18 @@
|
||||
# Phase 17 — Player-Bar Queue View
|
||||
|
||||
Status: **design spec — open questions pending Daniel.** Author: product-designer. Date: 2026-06-19.
|
||||
Status: **design spec — 4 of 11 open questions resolved (Daniel, 2026-06-19); 7 still pending.** Author: product-designer. Date: 2026-06-19.
|
||||
**Plan only — no code has been written by this doc.**
|
||||
|
||||
**Resolved (Daniel, 2026-06-19):** OQ1 → **Option A, conditional** (collapse/expand toggle *if* dynamic
|
||||
iframe resize is achievable in the embed snippet; **else fall back to Option B**, omit the button —
|
||||
feasibility call made during 17.3). OQ4 → **`MudDropContainer` for now** (pivot to a touch-viable
|
||||
mechanism later if mobile issues surface; C6 softened — touch-viability is a known risk, not a pre-ship
|
||||
blocker). OQ8 → **pure append, confirmed** (add ≠ play; first add into a dormant queue leaves a coherent
|
||||
`CurrentIndex` via a small additive engine affordance, landing with wave 17.1). OQ10 → **deferred,
|
||||
confirmed** (cards get no Add-to-Queue in Phase 17; the deferred card work is captured in `TODO.md`).
|
||||
The remaining seven (OQ2, OQ3, OQ5, OQ6, OQ7, OQ9, OQ11) are **still pending** — their §10
|
||||
recommendations stand but are not confirmed.
|
||||
|
||||
This phase makes the play-queue **visible and manipulable**. Phase 11 (wave 11.F) built the queue
|
||||
*engine* (`IQueueService` / `QueueService`) and wired auto-advance, skip-prev/next, and release
|
||||
embeds — but the queue itself has **no UI**. A listener can start an album and skip through it, but
|
||||
@@ -88,9 +98,12 @@ source, multiple views*).
|
||||
- **C5 — Reorder/remove are interop-free state mutations.** Like `Enqueue`/`Arm`, they touch only the
|
||||
in-memory list + index + `QueueChanged`. They run safely during prerender. Only `PlayRelease`/
|
||||
`Start`/`Next`/`Previous` touch JS.
|
||||
- **C6 — Drag-and-drop must be touch-viable.** The public site's primary listening surface includes
|
||||
mobile (per `PLAN.md §1.7`). Whatever DnD mechanism is chosen must work with touch, or the design
|
||||
must offer a non-drag fallback for reordering (up/down affordance). **Flag — see OQ4.**
|
||||
- **C6 — Drag-and-drop should be touch-viable (softened — OQ4 resolved).** The public site's primary
|
||||
listening surface includes mobile (per `PLAN.md §1.7`). **Resolved (Daniel, 2026-06-19): ship with
|
||||
`MudDropContainer` now.** Touch-viability is **no longer a hard pre-ship blocker** — it is a known
|
||||
risk with a planned pivot path: if mobile/touch issues surface in practice, pivot to a touch-viable
|
||||
mechanism (pointer-interop reorder, matching `RadialKnob`'s `capturePointer`, or an up/down-arrow
|
||||
fallback) in a later pass. See OQ4 (resolved).
|
||||
- **C7 — Embedded panel must not break the iframe host.** Adding the panel in Fixed mode grows the
|
||||
player's intrinsic height; the embed snippet's iframe dimensions must account for it (§4, OQ6).
|
||||
|
||||
@@ -169,15 +182,23 @@ the existing player-bar controls** — not a toggle overlay. It is part of the e
|
||||
toggling** — but rather than hide it, **repurpose it as a collapse/expand control** for the panel so a
|
||||
listener can reclaim the iframe space. Two viable readings, pick one:
|
||||
|
||||
- **Option A (recommend) — collapse toggle.** Queue button is present in Fixed mode and
|
||||
- **Option A (resolved — preferred) — collapse toggle.** Queue button is present in Fixed mode and
|
||||
collapses/expands the always-default-open panel. Default = expanded. Gives the embedder's viewer
|
||||
control without changing the snippet height (collapsed just shows less; the iframe stays sized for
|
||||
expanded). Consistent button meaning across modes ("toggle the queue view").
|
||||
- **Option B — omit the button in Fixed mode entirely.** Panel is always open, no toggle. Simpler,
|
||||
but the button's meaning then differs by mode (present+toggles-overlay when docked, absent when
|
||||
embedded), and a viewer can't reclaim space.
|
||||
control. Consistent button meaning across modes ("toggle the queue view").
|
||||
- **Option B (fallback) — omit the button in Fixed mode entirely.** Panel is always open, no toggle.
|
||||
Simpler, but the button's meaning then differs by mode (present+toggles-overlay when docked, absent
|
||||
when embedded), and a viewer can't reclaim space.
|
||||
|
||||
This is **OQ1** — Daniel's call. The brief explicitly flagged it.
|
||||
**OQ1 — RESOLVED (Daniel, 2026-06-19): Option A, *conditional on feasibility*.** Use Option A **if**
|
||||
the iframe can be dynamically resized appropriately for collapse/expand — e.g. an embed-snippet
|
||||
`postMessage` → host resize handshake so the host iframe shrinks when the panel collapses and grows
|
||||
when it expands. **Otherwise fall back to Option B** (omit the button, panel always open at fixed
|
||||
height). **A is preferred; B is the fallback; the deciding factor is whether dynamic iframe resize is
|
||||
achievable in the embed snippet.** This A-vs-B determination is **made during 17.3 implementation** —
|
||||
record it there. Note the interaction with OQ6 (embed panel height): a collapse/expand that does *not*
|
||||
resize the iframe (the earlier "iframe stays sized for expanded; collapsed just shows less" reading) is
|
||||
**not** Option A under this resolution — Option A requires the iframe to actually resize. A non-resizing
|
||||
collapse is cosmetic and does not let the viewer reclaim space, so it collapses into Option B's value.
|
||||
|
||||
---
|
||||
|
||||
@@ -192,14 +213,14 @@ An **"Add to Queue" icon button with a tooltip** beside **every play button for
|
||||
(existing member, no UI calls it today; this lights it up).
|
||||
- **Release context:** `IQueueService.EnqueueRange(orderedTracks)` — appends the whole release's
|
||||
ordered track list (existing member).
|
||||
- **First-add semantics (define):** if the queue is **empty/dormant** (`CurrentIndex == -1`), what
|
||||
does "Add to Queue" do? `Enqueue` appends but does not set a current index or start playback, so
|
||||
adding to an empty queue leaves it with items but `Current == null` and nothing playing. Options:
|
||||
(a) pure append, listener must press play; (b) if dormant, first add also stages/sets current
|
||||
without auto-playing; (c) if dormant, first add behaves like `PlayRelease`/play. **Recommend (a)**
|
||||
— Add-to-Queue is explicitly *not* play; keep the verbs distinct. But this needs a tiny engine
|
||||
affordance so an appended-into-empty queue has a sensible `CurrentIndex` for the next skip/play.
|
||||
**OQ8.**
|
||||
- **First-add semantics — RESOLVED (Daniel, 2026-06-19): pure append (option (a)).** Add-to-Queue is
|
||||
explicitly *not* play; keep the verbs distinct. If the queue is **empty/dormant** (`CurrentIndex ==
|
||||
-1`), the first add appends and **leaves a coherent `CurrentIndex`** (the small additive engine
|
||||
affordance) so the next play/skip behaves correctly — but **does not auto-play**. The listener still
|
||||
presses play to start. (Options (b) "first add also stages/sets current without auto-playing" and (c)
|
||||
"first add behaves like `PlayRelease`/play" are declined — they blur add vs. play.) **This engine
|
||||
tweak belongs with wave 17.1** (it is part of the `Enqueue`-into-empty index handling, alongside the
|
||||
`Move`/`RemoveAt` additions). See **OQ8 (resolved)**.
|
||||
|
||||
### 5.1 Where the button attaches (inventory)
|
||||
|
||||
@@ -214,10 +235,11 @@ Every site that currently has a play affordance:
|
||||
| `ReleaseGallery` cards | **none today** (cards are pure links) | **scope question — OQ10** |
|
||||
|
||||
- **`ReleaseGallery` cards have no play button today** — they navigate to detail. Adding an
|
||||
Add-to-Queue button there is *new* affordance, arguably out of the literal brief ("anywhere there
|
||||
is a play button"). **OQ10** — do cards get one? If yes, they probably want a play button too, which
|
||||
is a bigger card-redesign question. Recommend: **defer card-level affordances**; scope item 4 to the
|
||||
detail-page play sites (rows 1–3 above) where a play button genuinely exists today.
|
||||
Add-to-Queue button there is *new* affordance, out of the literal brief ("anywhere there is a play
|
||||
button"). **OQ10 — RESOLVED (Daniel, 2026-06-19): deferred, confirmed.** Cards get **no**
|
||||
Add-to-Queue affordance in Phase 17. Scope item 4 to the detail-page play sites (rows 1–3 above)
|
||||
where a play button genuinely exists today. The deferred work — giving cards a play + Add-to-Queue
|
||||
affordance (a card-redesign question) — is captured as a `TODO.md` entry.
|
||||
- **`StreamNowButton`** is a "surprise me" trigger, not a fixed track — Add-to-Queue has no concrete
|
||||
item until a track resolves. Recommend: **exclude it** from item 4. **OQ9.**
|
||||
|
||||
@@ -331,32 +353,40 @@ Component (if/when component test coverage is in scope — today none exists for
|
||||
|
||||
## 10. Open questions for Daniel
|
||||
|
||||
- **OQ1 — Queue button in embed (Fixed) mode.** Panel is always shown there. Option A: keep the
|
||||
button as a collapse/expand toggle (recommend). Option B: omit the button entirely. **Daniel's
|
||||
call** — explicitly flagged in the brief.
|
||||
**Four resolved (Daniel, 2026-06-19): OQ1, OQ4, OQ8, OQ10. Seven still pending: OQ2, OQ3, OQ5, OQ6,
|
||||
OQ7, OQ9, OQ11 — their recommendations below stand but are not confirmed.**
|
||||
|
||||
- **OQ1 — Queue button in embed (Fixed) mode. RESOLVED → Option A, conditional.** Use Option A
|
||||
(collapse/expand toggle) **if** the iframe can be dynamically resized for collapse/expand (embed-snippet
|
||||
`postMessage` → host resize handshake); **else fall back to Option B** (omit the button). A preferred,
|
||||
B fallback; deciding factor = whether dynamic iframe resize is achievable in the embed snippet;
|
||||
determination made during **17.3** (see §4.1).
|
||||
- **OQ2 — Click-to-jump.** Does clicking a queued row jump playback to that track? Recommend **yes**
|
||||
in both modes (reuses `PlayRelease(Items, index)`); jump is not a forbidden edit, only reorder/
|
||||
remove are. Confirm for the read-only embed too.
|
||||
- **OQ3 — Terminal/empty states.** When removal empties the queue mid-session: close the overlay?
|
||||
Show an empty state then auto-close? And when the *current* track is removed, what should the panel
|
||||
and the player show?
|
||||
- **OQ4 — Drag-and-drop mechanism & touch.** MudBlazor has `MudDropContainer` (HTML5 DnD, weak on
|
||||
touch) vs. a JS-interop pointer-drag (like `RadialKnob`'s `capturePointer`) vs. a non-drag
|
||||
up/down-arrow reorder fallback. Mobile is a primary surface (C6). **Which mechanism?** Recommend:
|
||||
pointer-based interop reorder (touch-viable, matches the codebase's existing pointer-capture
|
||||
pattern) **or** ship up/down arrows for v1 and add drag later. Daniel's taste call.
|
||||
- **OQ4 — Drag-and-drop mechanism & touch. RESOLVED → `MudDropContainer` for now.** Ship with
|
||||
MudBlazor's `MudDropContainer`. If mobile/touch issues surface in practice, pivot to a touch-viable
|
||||
mechanism later (pointer-based interop reorder matching `RadialKnob`'s `capturePointer`, or an
|
||||
up/down-arrow fallback). C6 softened: touch-viability is a known risk with a planned pivot path, **not**
|
||||
a hard pre-ship blocker (see §2 C6).
|
||||
- **OQ5 — "Clear queue" in the UI.** Include a Clear action in the overlay header? Does Clear stop
|
||||
playback or just empty the up-next (engine's `Clear` does not stop the player today)?
|
||||
- **OQ6 — Embed panel height.** Fixed sensible height with internal scroll past N rows (recommend),
|
||||
vs. height that grows with track count up to a cap. Affects `EmbedSnippetBuilder.ForRelease`.
|
||||
- **OQ7 — Glyph.** Material `QueueMusic`/`PlaylistAdd`, or a bespoke hand-rolled `DDIcons` queue
|
||||
glyph to match the gas-lamp/lava-lamp family aesthetic?
|
||||
- **OQ8 — Add-to-Queue into a dormant (empty) queue.** Pure append (recommend — keep "add" ≠ "play"),
|
||||
vs. first-add also stages current, vs. first-add plays. Affects the engine's index handling.
|
||||
- **OQ8 — Add-to-Queue into a dormant (empty) queue. RESOLVED → pure append.** Add ≠ play; first add
|
||||
into a dormant queue appends and leaves a coherent `CurrentIndex` (small additive engine affordance)
|
||||
so the next play/skip behaves correctly, but does **not** auto-play. The engine tweak lands with wave
|
||||
**17.1**. (first-add-stages and first-add-plays both declined — see §5.)
|
||||
- **OQ9 — `StreamNowButton`.** Exclude from Add-to-Queue (recommend — no fixed track until resolved)?
|
||||
- **OQ10 — `ReleaseGallery` cards.** Do browse-grid cards get an Add-to-Queue (and implicitly a play)
|
||||
button? Recommend **defer** — cards have no play button today; adding one is a card redesign beyond
|
||||
this brief. Scope item 4 to the detail-page play sites.
|
||||
- **OQ10 — `ReleaseGallery` cards. RESOLVED → deferred, confirmed.** Browse-grid cards get **no**
|
||||
Add-to-Queue affordance in Phase 17. Item 4 is scoped to the detail-page play sites (Cut header, Cut
|
||||
track rows, Session/Mix hero). The deferred card work (play + Add-to-Queue, a card-redesign question)
|
||||
is captured in `TODO.md`.
|
||||
- **OQ11 — Removing the current track.** Confirm the recommended "keep playing to natural end, don't
|
||||
stop" behavior (C2-consistent) vs. "removing current skips to next immediately."
|
||||
|
||||
@@ -368,15 +398,20 @@ Three waves; **17.1 is the load-bearing prerequisite** (engine + the shared queu
|
||||
modes render). 17.2 and 17.3 then hang off it and are largely parallel.
|
||||
|
||||
- **17.1 — Engine additions + shared queue-list view.** Add `Move`/`RemoveAt` to `IQueueService`/
|
||||
`QueueService` (+ `QueueServiceTests`). Build a single presentational `QueueList` component that
|
||||
renders `Items` with the current marked and takes an `Editable` flag (drag/remove on when true).
|
||||
This is the *one source* both modes consume. **Cold-start. Gates 17.2 + 17.3.** No bar changes yet.
|
||||
`QueueService` (+ `QueueServiceTests`). **Plus the OQ8 affordance:** `Enqueue` into a dormant/empty
|
||||
queue leaves a coherent `CurrentIndex` (pure append, no auto-play) so the next play/skip is correct.
|
||||
Build a single presentational `QueueList` component that renders `Items` with the current marked and
|
||||
takes an `Editable` flag (drag/remove on when true; reorder via `MudDropContainer` per OQ4). This is
|
||||
the *one source* both modes consume. **Cold-start. Gates 17.2 + 17.3.** No bar changes yet.
|
||||
- **17.2 — Non-Fixed overlay.** Queue button in the bar (gated on `Items.Count > 0`, placed per
|
||||
§3.1), the centered overlay borrowing the visualizer-popover idiom, hosting `QueueList Editable`.
|
||||
Reorder/remove/jump wired. **Depends on 17.1.**
|
||||
- **17.3 — Fixed embed panel + snippet resize + Add-to-Queue.** Inline `QueueList` (non-editable)
|
||||
below the Fixed bar; the (OQ1) button behavior; `EmbedSnippetBuilder.ForRelease` height bump;
|
||||
the Add-to-Queue buttons at the detail-page play sites (§5.1 grounded scope). **Depends on 17.1.**
|
||||
below the Fixed bar; **the OQ1 feasibility determination is made here** — implement Option A
|
||||
(collapse/expand button + iframe resize handshake) **if** dynamic iframe resize proves achievable in
|
||||
the embed snippet, else fall back to Option B (omit the button); `EmbedSnippetBuilder.ForRelease`
|
||||
height bump; the Add-to-Queue buttons at the detail-page play sites (§5.1 grounded scope — **cards
|
||||
excluded per OQ10**). **Depends on 17.1.**
|
||||
(Add-to-Queue could split into its own wave 17.4 if Daniel wants it shipped independently — it only
|
||||
needs the existing `Enqueue`/`EnqueueRange`, not 17.1's new members.)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user