the move, the two unguarded blocks that shared its slot, and the line that says which version you chose
What was actually in that slot
The report says one control. Reading it, there were three, and only the
first was guarded by "is there even a choice":
the selector, behind distinctTracklistCount() <= 1;
a Versions / Loading releases… block with no guard, so it took
the primary position on every album load — beside renderTracklist's own "Loading tracks…", which is the same fetch
reported twice;
a Versions / <error> block, also unguarded, duplicating what catalog-scope-notice shows at the top of the page with a retry —
every path that sets errorReleases also sets catalogFailed,
which is the only route to unavailable.
Plus renderVersionMeta, which explains in prose above the tracklist
that the standard version is picked "by weighing how many physical
releases share it, release status, and release date". That is a
sentence about our clustering heuristic in the most valuable space on
the page.
The shape
"Other versions of this album (N)", below the tracklist, collapsed. A
real <button aria-expanded aria-controls> inside the heading that
names the section, body rendered unconditionally and toggled with hidden — both config-section's rules, not new ones, and the second
because aria-controls has to name an element that is in the DOM.
Of the three placements the Direction offers: the overflow menu needs a
menu this page does not have, and "near the release metadata" puts the
control in the header while its panel lives elsewhere, which splits aria-controls from the thing it names.
Why this was a rewrite and not a move
renderTracklist returned nothing on errorReleases and leaned on
the selector's own error block to have said it. A control inside a
collapsed disclosure cannot be a page's error surface. The failure
belongs to the list that is missing because of it, so that is where it
is drawn now — and the duplicate at the top of the page stops being a
duplicate.
What had to survive
The ★ and the words "in your library" on the matching entry,
unchanged, inside the panel.
Which version is on screen. The default is what the header
already describes, so stating it on every album would be this issue's
own complaint one size smaller. defaultVersionKey is the test: a
line appears above the tracklist only once someone has chosen
another, naming it and offering the way back.
The panel stays open after a choice. A panel that shuts on use
cannot be used twice.
The <select> also loses an aria-label of "Select release version"
that outranked its own visible <label>Version</label> — a label not
in the name.
The "Show the whole album" switch stays where it is: that is #7's
control, it is not a metadata task, and it belongs next to the list it
changes.
Verification actually run
make ui-test # 883 passed (77 files), up from 871
frontend/node_modules/.bin/tsc --noEmit # clean
make e2e # 114 passed, chromium, against a seeded app
make css-check # 127 files, no broken literals
12 new specs in album-version-demotion.test.ts. The disclosure's name
goes through page.getByRole('button', …) — the browser's own answer —
because a disclosure that cannot be tabbed to is the fault config-section shipped for every setting in the app, and a shadow
query cannot tell you a control has a name.
And it was looked at, not only asserted. Against make dev-headless SEED=default, driving the real component in the real app
(where the theme actually reaches :root, which the component tier
cannot see): the collapsed page, the open panel, a chosen version
swapping the tracklist from 10 rows to 14, and 390×800 with document.body.scrollWidth === 390.
Filed on the way
#119 — dev-headless silently talks to whatever already holds
its port. A yj-dev orphaned by a deleted worktree two days ago made make sandbox-seed fail with no such table: libraries against a
fresh YJ_HOME, which reads exactly like a schema bug and is not.
A comment on #66 rather than a new issue, since that Direction
names the version selector as a likely culprit for the phone-width
overflow: it is no longer in the header row at all, and the real
culprit is measured there — the cover art keeps its desktop size, so
the title renders as G… and "Request this" is clipped, while body.scrollWidth stays equal to the viewport. That last part is why layout-overflow.spec.ts cannot see it.
Releases are manual (#115), so merging cuts no version.
Closes #17 — the last Phase 1 item before #28, and the one #73 pairs
with #38 as "same page, do it in the same pass".
## Commits
| commit | issue | what |
| --- | --- | --- |
| `905654c` feat(explore): demote the album page's version selector to a disclosure | #17 | the move, the two unguarded blocks that shared its slot, and the line that says which version you chose |
## What was actually in that slot
The report says one control. Reading it, there were three, and only the
first was guarded by "is there even a choice":
1. the selector, behind `distinctTracklistCount() <= 1`;
2. a `Versions / Loading releases…` block with **no** guard, so it took
the primary position on every album load — beside
`renderTracklist`'s own "Loading tracks…", which is the same fetch
reported twice;
3. a `Versions / <error>` block, also unguarded, duplicating what
`catalog-scope-notice` shows at the top of the page *with a retry* —
every path that sets `errorReleases` also sets `catalogFailed`,
which is the only route to `unavailable`.
Plus `renderVersionMeta`, which explains in prose above the tracklist
that the standard version is picked "by weighing how many physical
releases share it, release status, and release date". That is a
sentence about our clustering heuristic in the most valuable space on
the page.
## The shape
"Other versions of this album (N)", below the tracklist, collapsed. A
real `<button aria-expanded aria-controls>` inside the heading that
names the section, body rendered unconditionally and toggled with
`hidden` — both `config-section`'s rules, not new ones, and the second
because `aria-controls` has to name an element that is in the DOM.
Of the three placements the Direction offers: the overflow menu needs a
menu this page does not have, and "near the release metadata" puts the
control in the header while its panel lives elsewhere, which splits
`aria-controls` from the thing it names.
## Why this was a rewrite and not a move
`renderTracklist` returned `nothing` on `errorReleases` and leaned on
the selector's own error block to have said it. A control inside a
collapsed disclosure cannot be a page's error surface. The failure
belongs to the list that is missing because of it, so that is where it
is drawn now — and the duplicate at the top of the page stops being a
duplicate.
## What had to survive
- **The ★ and the words "in your library"** on the matching entry,
unchanged, inside the panel.
- **Which version is on screen.** The default is what the header
already describes, so stating it on every album would be this issue's
own complaint one size smaller. `defaultVersionKey` is the test: a
line appears above the tracklist *only* once someone has chosen
another, naming it and offering the way back.
- **The panel stays open after a choice.** A panel that shuts on use
cannot be used twice.
- The `<select>` also loses an `aria-label` of "Select release version"
that outranked its own visible `<label>Version</label>` — a label not
in the name.
The "Show the whole album" switch stays where it is: that is #7's
control, it is not a metadata task, and it belongs next to the list it
changes.
## Verification actually run
```
make ui-test # 883 passed (77 files), up from 871
frontend/node_modules/.bin/tsc --noEmit # clean
make e2e # 114 passed, chromium, against a seeded app
make css-check # 127 files, no broken literals
```
12 new specs in `album-version-demotion.test.ts`. The disclosure's name
goes through `page.getByRole('button', …)` — the browser's own answer —
because a disclosure that cannot be tabbed to is the fault
`config-section` shipped for every setting in the app, and a shadow
query cannot tell you a control has a name.
**And it was looked at, not only asserted.** Against `make
dev-headless SEED=default`, driving the real component in the real app
(where the theme actually reaches `:root`, which the component tier
cannot see): the collapsed page, the open panel, a chosen version
swapping the tracklist from 10 rows to 14, and 390×800 with
`document.body.scrollWidth === 390`.
## Filed on the way
- **#119** — `dev-headless` silently talks to whatever already holds
its port. A `yj-dev` orphaned by a deleted worktree two days ago made
`make sandbox-seed` fail with `no such table: libraries` against a
fresh `YJ_HOME`, which reads exactly like a schema bug and is not.
- **A comment on #66** rather than a new issue, since that Direction
names the version selector as a likely culprit for the phone-width
overflow: it is no longer in the header row at all, and the real
culprit is measured there — the cover art keeps its desktop size, so
the title renders as `G…` and "Request this" is clipped, while
`body.scrollWidth` stays equal to the viewport. That last part is why
`layout-overflow.spec.ts` cannot see it.
Releases are manual (#115), so merging cuts no version.
Closes #17
Choosing which pressing you are looking at is an advanced,
metadata-repair task, and it sat directly above the tracklist with a
heading, a `<select>` and a paragraph explaining how our clustering
picks a "standard version" by weighing release count, status and date.
That is a sentence about our own heuristic in the most valuable space
on the page.
It is now "Other versions of this album (N)" below the tracklist: a
real `<button aria-expanded aria-controls>` inside the heading that
names the section, with the body rendered unconditionally and toggled
with `hidden`, because `aria-controls` has to name an element that is
in the DOM. Both rules are `config-section`'s rather than new ones.
It is demoted, not removed — matching the wrong release is a real
problem and this is how it gets fixed.
**Two more blocks shared that slot and neither was guarded.** The
selector at least had `distinctTracklistCount() <= 1`; the
`Versions / Loading releases…` spinner and the `Versions / <error>`
block did not, so both took the primary position on every album
regardless of whether there was ever going to be a choice. The spinner
said what `renderTracklist` was already saying about the same fetch, so
it is gone. The error was the one `catalog-scope-notice` shows at the
top of the page with a retry — every path that sets `errorReleases`
also sets `catalogFailed`, the only route to `unavailable`.
That error is what made this a rewrite rather than a move.
`renderTracklist` returned `nothing` on `errorReleases` and leaned on
the selector's own block to have said it, and a control inside a
collapsed disclosure cannot be a page's error surface. The failure
belongs to the list that is missing because of it, so that is where it
is drawn.
**What must not be lost is which version is on screen.** The default is
what the header already describes, so saying it on every album would be
this issue's own complaint one size smaller. `defaultVersionKey` is the
test: a line appears above the tracklist only once someone has chosen
another, naming it and offering the way back. The ★ and the words "in
your library" survive unchanged inside the panel, and the panel does
not close when the selection changes — a panel that shuts on use cannot
be used twice.
The `<select>` also loses an `aria-label` of "Select release version"
that outranked its own visible `<label>Version</label>`, which is a
label not in the name.
Verified against the running app as well as the suite: the collapsed
page, the open panel, a chosen version and 390px width all read
correctly, and the shell still measures 390 in a 390 viewport.
Closes#17
logan
merged commit 9375f25629 into main2026-08-19 05:38:26 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #17 — the last Phase 1 item before #28, and the one #73 pairs
with #38 as "same page, do it in the same pass".
Commits
905654cfeat(explore): demote the album page's version selector to a disclosureWhat was actually in that slot
The report says one control. Reading it, there were three, and only the
first was guarded by "is there even a choice":
distinctTracklistCount() <= 1;Versions / Loading releases…block with no guard, so it tookthe primary position on every album load — beside
renderTracklist's own "Loading tracks…", which is the same fetchreported twice;
Versions / <error>block, also unguarded, duplicating whatcatalog-scope-noticeshows at the top of the page with a retry —every path that sets
errorReleasesalso setscatalogFailed,which is the only route to
unavailable.Plus
renderVersionMeta, which explains in prose above the tracklistthat the standard version is picked "by weighing how many physical
releases share it, release status, and release date". That is a
sentence about our clustering heuristic in the most valuable space on
the page.
The shape
"Other versions of this album (N)", below the tracklist, collapsed. A
real
<button aria-expanded aria-controls>inside the heading thatnames the section, body rendered unconditionally and toggled with
hidden— bothconfig-section's rules, not new ones, and the secondbecause
aria-controlshas to name an element that is in the DOM.Of the three placements the Direction offers: the overflow menu needs a
menu this page does not have, and "near the release metadata" puts the
control in the header while its panel lives elsewhere, which splits
aria-controlsfrom the thing it names.Why this was a rewrite and not a move
renderTracklistreturnednothingonerrorReleasesand leaned onthe selector's own error block to have said it. A control inside a
collapsed disclosure cannot be a page's error surface. The failure
belongs to the list that is missing because of it, so that is where it
is drawn now — and the duplicate at the top of the page stops being a
duplicate.
What had to survive
unchanged, inside the panel.
already describes, so stating it on every album would be this issue's
own complaint one size smaller.
defaultVersionKeyis the test: aline appears above the tracklist only once someone has chosen
another, naming it and offering the way back.
cannot be used twice.
<select>also loses anaria-labelof "Select release version"that outranked its own visible
<label>Version</label>— a label notin the name.
The "Show the whole album" switch stays where it is: that is #7's
control, it is not a metadata task, and it belongs next to the list it
changes.
Verification actually run
12 new specs in
album-version-demotion.test.ts. The disclosure's namegoes through
page.getByRole('button', …)— the browser's own answer —because a disclosure that cannot be tabbed to is the fault
config-sectionshipped for every setting in the app, and a shadowquery cannot tell you a control has a name.
And it was looked at, not only asserted. Against
make dev-headless SEED=default, driving the real component in the real app(where the theme actually reaches
:root, which the component tiercannot see): the collapsed page, the open panel, a chosen version
swapping the tracklist from 10 rows to 14, and 390×800 with
document.body.scrollWidth === 390.Filed on the way
dev-headlesssilently talks to whatever already holdsits port. A
yj-devorphaned by a deleted worktree two days ago mademake sandbox-seedfail withno such table: librariesagainst afresh
YJ_HOME, which reads exactly like a schema bug and is not.names the version selector as a likely culprit for the phone-width
overflow: it is no longer in the header row at all, and the real
culprit is measured there — the cover art keeps its desktop size, so
the title renders as
G…and "Request this" is clipped, whilebody.scrollWidthstays equal to the viewport. That last part is whylayout-overflow.spec.tscannot see it.Releases are manual (#115), so merging cuts no version.
Closes #17