Desktop: content is obscured or unusable at small window sizes — decide the supported sizes and the modes #24

Closed
opened 2026-08-18 05:55:00 +00:00 by logan · 2 comments
Collaborator

Report

Small window sizes are handled badly. With the queue panel open in a small window, content gets covered — e.g. the Playlists page's header management buttons disappear behind the queue panel. Possible answers: make the queue panel obviously an overlay over the content so it reads as something to close, allow horizontal scrolling in the main panel, or switch modes (even down to the mini-player) below some size. Needs discussion, and we should state what window sizes are actually supported.

Findings

  • The window minimum is 800x600, chosen because that is where the shell was measured to still work (below ~780 the header subtitle wraps the title out of the 4em bar; below ~600 tall the sidebar items stop fitting at once — the sidebar scrolls now and collapses to icons below 900px).
  • body is overflow-x: auto; overflow-y: hidden; the shell fits 320px viewports at 400% zoom because everything between the viewport and the shrinkable content carries min-width: 0 and each component states what it drops.
  • Under 600px the phone layout takes over (sidebar column dropped, <bottom-nav>). Between 600 and 800 there is no phone layout and no guarantee.
  • The queue panel takes layout space rather than overlaying, which is why it can push/cover a page header.

Direction

Treat this as a design pass, not a patch:

  1. Write down the supported size matrix (phone <600, the 600-800 gap, desktop, and what 400% zoom promises).
  2. Decide the queue panel's model — inline column above some width, overlay drawer below it — and give it a visible scrim so "close me" is obvious.
  3. Audit page headers for buttons that vanish rather than collapsing into an overflow menu (Playlists is the reported one; Android reports the same page).
  4. Decide whether a very small window becomes the mini-player (see the mini-player issue) or simply refuses to go there.
**Report** Small window sizes are handled badly. With the queue panel open in a small window, content gets covered — e.g. the Playlists page's header management buttons disappear behind the queue panel. Possible answers: make the queue panel obviously an overlay *over* the content so it reads as something to close, allow horizontal scrolling in the main panel, or switch modes (even down to the mini-player) below some size. Needs discussion, and we should state what window sizes are actually supported. **Findings** - The window minimum is 800x600, chosen because that is where the shell was measured to still work (below ~780 the header subtitle wraps the title out of the 4em bar; below ~600 tall the sidebar items stop fitting at once — the sidebar scrolls now and collapses to icons below 900px). - `body` is `overflow-x: auto; overflow-y: hidden`; the shell fits 320px viewports at 400% zoom because everything between the viewport and the shrinkable content carries `min-width: 0` and each component states what it drops. - Under 600px the phone layout takes over (sidebar column dropped, `<bottom-nav>`). Between 600 and 800 there is no phone layout and no guarantee. - The queue panel takes layout space rather than overlaying, which is why it can push/cover a page header. **Direction** Treat this as a design pass, not a patch: 1. Write down the supported size matrix (phone <600, the 600-800 gap, desktop, and what 400% zoom promises). 2. Decide the queue panel's model — inline column above some width, overlay drawer below it — and give it a visible scrim so "close me" is obvious. 3. Audit page headers for buttons that vanish rather than collapsing into an overflow menu (Playlists is the reported one; Android reports the same page). 4. Decide whether a very small window becomes the mini-player (see the mini-player issue) or simply refuses to go there.
logan self-assigned this 2026-08-19 14:10:56 +00:00
logan added the
Status
In Progress
label 2026-08-19 14:10:58 +00:00
Author
Collaborator

Claiming this. Branch: feat/24-supported-sizes-queue-model.

Approach. Treating it as the design pass the Direction asks for, so the
first deliverable is a plan document in .planning/plans/active/ rather than
a patch — #73 has the rest of Phase 2 hanging off the decision, and #55 is
blocked on it, so the decision needs to be written down and arguable before
any CSS moves.

Order of work:

  1. Measure the current failure modes against the running app at each candidate
    breakpoint (screenshots, not just assertions — layout-overflow.spec.ts
    passes on a build whose header clips its own buttons, so the shell-level
    assertion cannot see this class of fault).
  2. Write the plan: the supported size matrix, the queue panel's model, and the
    two scope decisions (#69 in this PR or its own, #12 mini-player as a mode or
    a refusal).
  3. Implement, with the matrix as the spec.

I will report back here with the matrix before implementing, and say on #55
whether this unblocks it.

Claimed by hand rather than with issue.sh claim: the token has write:issue
but not read:user, so me() fails. Filed separately.

Claiming this. Branch: `feat/24-supported-sizes-queue-model`. **Approach.** Treating it as the design pass the Direction asks for, so the first deliverable is a plan document in `.planning/plans/active/` rather than a patch — #73 has the rest of Phase 2 hanging off the decision, and #55 is blocked on it, so the decision needs to be written down and arguable before any CSS moves. Order of work: 1. Measure the current failure modes against the running app at each candidate breakpoint (screenshots, not just assertions — `layout-overflow.spec.ts` passes on a build whose header clips its own buttons, so the shell-level assertion cannot see this class of fault). 2. Write the plan: the supported size matrix, the queue panel's model, and the two scope decisions (#69 in this PR or its own, #12 mini-player as a mode or a refusal). 3. Implement, with the matrix as the spec. I will report back here with the matrix before implementing, and say on #55 whether this unblocks it. Claimed by hand rather than with `issue.sh claim`: the token has `write:issue` but not `read:user`, so `me()` fails. Filed separately.
Author
Collaborator

Plan written: .planning/plans/active/018-supported-sizes-and-the-queue-model.md
(branch feat/24-supported-sizes-queue-model). The matrix, as promised, plus
five measurements that are not in this issue.

Measured, against the running app (Chromium, Playlists, seed default)

viewport sidebar queue main panel header needs actions clipped
1280x800 200 open 321 759 759
1000x700 200 open 321 479 747 New Playlist, New Smart Playlist
900x600 200 open 321 379 747 all three
800x600 56 open 321 423 747 all three
390x780 open 321 69 747 all three
320x600 open 321 0 747 all three
800x600 56 closed 744 747 New Smart Playlist (158/162px)
  1. The header clips at the supported minimum with the queue closed. 800x600
    is the size window.go enforces and the only size this app promises, and
    "New Smart Playlist" loses 4px of its 162 there. This reads as a queue bug;
    the queue makes it dramatic, but the header overflows on its own.
  2. 900x600 is worse than 800x600. The sidebar collapses to icons below
    900, so main is 843px at 899 and 700px at 900. The worst desktop case is the
    pixel above the collapse, not the minimum — so a test that checks "the
    minimum" and stops has not checked the worst case, which is what
    layout-overflow.spec.ts does today.
  3. At phone widths the queue is an amputation, not a drawer. The host is
    flex-shrink: 0 and in the flow of .content-area, so it takes width from
    the content rather than covering it: 69px of page left at 390px, and 0px
    at 320px.
  4. Only Playlists overflows — all ten primary views swept at 900x600 and
    390x780, everything else reports scrollWidth == clientWidth. See #69.
  5. Both reasons in MinWidth's comment are stale. The subtitle is
    display: none below 900, and the sidebar host is overflow-y: auto
    (scrollHeight 434 vs 332px client at 600x460, Settings reachable after
    scrolling). Neither mechanism can happen any more. The floor should stay;
    its stated reason no longer supports it.

The four decisions

  1. Three bands — Phone (<600, reflow, fits 320), Compact (600–899, icon
    sidebar), Desktop (>=900). Two already exist; what is new is that they are a
    written promise, that the queue is part of it, and one sentence across all
    three: no action is ever unreachable.
  2. The queue is inline only while
    viewport - sidebar - queueWidth >= 480,
    and an overlay with a scrim
    otherwise. It cannot be a media query: the panel is drag-resizable
    200–500px and persisted, so a fixed breakpoint assumes the default 320 and
    is wrong by 180px for a user who widened it — in the direction that hurts.
    480 is a judgement and the plan says so: there is no cliff (the track list
    rescales continuously, 213px to 124px columns with no row overflow), so it
    is anchored to keep the default 1100 window inline while putting every
    measured-broken case on the overlay side.
  3. #69 is its own PR, on a finding rather than an estimate — see the comment
    I am leaving there.
  4. A very small window becomes the phone layout, not the mini-player. #12 is
    a second window (AlwaysOnTop is a window option, and it needs its own
    entry branch); making it a mode of the main window would discard navigation
    state on a resize and put #12's own process-level MPRIS question on a path a
    drag can trigger. The reflow already exists and is already tested, which is
    a better answer than refusing. #12 is not coupled to this.

Implementing phases 2–4 next.

Plan written: `.planning/plans/active/018-supported-sizes-and-the-queue-model.md` (branch `feat/24-supported-sizes-queue-model`). The matrix, as promised, plus five measurements that are not in this issue. ## Measured, against the running app (Chromium, Playlists, seed `default`) | viewport | sidebar | queue | main panel | header needs | actions clipped | |---|---|---|---|---|---| | 1280x800 | 200 | open 321 | 759 | 759 | — | | 1000x700 | 200 | open 321 | 479 | 747 | New Playlist, New Smart Playlist | | **900x600** | 200 | open 321 | **379** | 747 | **all three** | | 800x600 | 56 | open 321 | 423 | 747 | all three | | 390x780 | — | open 321 | **69** | 747 | all three | | 320x600 | — | open 321 | **0** | 747 | all three | | **800x600** | 56 | closed | 744 | 747 | **New Smart Playlist (158/162px)** | 1. **The header clips at the supported minimum with the queue closed.** 800x600 is the size `window.go` enforces and the only size this app promises, and "New Smart Playlist" loses 4px of its 162 there. This reads as a queue bug; the queue makes it dramatic, but the header overflows on its own. 2. **900x600 is worse than 800x600.** The sidebar collapses to icons *below* 900, so main is 843px at 899 and 700px at 900. The worst desktop case is the pixel above the collapse, not the minimum — so a test that checks "the minimum" and stops has not checked the worst case, which is what `layout-overflow.spec.ts` does today. 3. **At phone widths the queue is an amputation, not a drawer.** The host is `flex-shrink: 0` and in the flow of `.content-area`, so it takes width from the content rather than covering it: 69px of page left at 390px, and **0px** at 320px. 4. **Only Playlists overflows** — all ten primary views swept at 900x600 and 390x780, everything else reports `scrollWidth == clientWidth`. See #69. 5. **Both reasons in `MinWidth`'s comment are stale.** The subtitle is `display: none` below 900, and the sidebar host is `overflow-y: auto` (`scrollHeight` 434 vs 332px client at 600x460, Settings reachable after scrolling). Neither mechanism can happen any more. The floor should stay; its stated reason no longer supports it. ## The four decisions 1. **Three bands** — Phone (<600, reflow, fits 320), Compact (600–899, icon sidebar), Desktop (>=900). Two already exist; what is new is that they are a written promise, that the queue is part of it, and one sentence across all three: **no action is ever unreachable**. 2. **The queue is inline only while `viewport - sidebar - queueWidth >= 480`,** and an overlay with a scrim otherwise. **It cannot be a media query**: the panel is drag-resizable 200–500px and persisted, so a fixed breakpoint assumes the default 320 and is wrong by 180px for a user who widened it — in the direction that hurts. 480 is a judgement and the plan says so: there is no cliff (the track list rescales continuously, 213px to 124px columns with no row overflow), so it is anchored to keep the default 1100 window inline while putting every measured-broken case on the overlay side. 3. **#69 is its own PR**, on a finding rather than an estimate — see the comment I am leaving there. 4. **A very small window becomes the phone layout, not the mini-player.** #12 is a *second window* (`AlwaysOnTop` is a window option, and it needs its own entry branch); making it a mode of the main window would discard navigation state on a resize and put #12's own process-level MPRIS question on a path a drag can trigger. The reflow already exists and is already tested, which is a better answer than refusing. #12 is not coupled to this. Implementing phases 2–4 next.
logan closed this issue 2026-08-19 15:22:40 +00:00
gitea-actions bot removed the
Status
In Progress
label 2026-08-19 15:22:49 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yonlu/yellowjacket#24