Answers #34 — Phase 1 item 3 of the roadmap (#73), and with #16 merged this leaves #38 unblocked.
The survey
Every <wa-icon> with a label beside it, across frontend/src:
meaning
before
after
Play / Play Next
play / forward-step
unchanged
Add to Queue
plus ×5, list ×1
bars-staggered
Add to Playlist
plus — the same glyph, adjacent in the same menu
list
the queue itself
list — also the Playlists nav item
bars-staggered
a playlist / Playlists nav
list
list
New Playlist, drop zones
plus
plus
can be requested
plus
regular/bookmark
requested
bookmark
solid/bookmark
in your library
check
unchanged
plus carried four meanings, two of them side by side in one menu; list carried three.
The rule
An icon names the noun it acts on, not the verb. "Add to queue" and "add to playlist" are one verb on two nouns, so the noun is what has to differ — which is why adding to a playlist wears the Playlists destination's own icon, and why the queue took bars-staggered and stopped wearing Playlists'. plus keeps the one thing it is unambiguous about.
bars-staggered is the only new glyph, confirmed present in Font Awesome Free 7.3.1 and vendored through names.txt + fetch-icons.mjs.
Commits
Commit
Issue
refactor(ui): give the icons one vocabulary and sweep the call sites
The fix was already in the repo, unused.explore-album-details's "Request this" button has used the regular/bookmark → solid/bookmark pair since it was written, while the badge forty pixels away showed a plus for the same state. That is utils/library-status.ts's fault one layer down: it made the two agree on what wanting means and left them disagreeing on what it looks like.
A live bug.explore-artist-details's Follow button was bookmark-check — Font Awesome Pro, never bundled — so it has drawn the missing-icon fallback, a circled question mark, for every followed artist since it was written. requested-badge.spec.ts exists for exactly this bug on the album button and says so in its docstring; this is the same bug one component over, still live, because offline-icons.spec.ts sweeps __yjIconMisses and no spec had ever followed an artist.
Verification actually run
make ui-test — 855 passed (75 files), up from 854.
icon-language.test.ts — 11 specs. Two of them are the point:
it sweeps the source. Reads every src/**/*.ts as raw text and fails on a governed name written outside the table — same shape as TestNoDirectRuntimeEmits, because the rule is about every call site and checking one checks nothing. Verified it fails by reintroducing one name="plus" in track-list.ts and watching it name the file.
it asserts every ICON_* is bundled, which is what turns a Pro name into a failing test rather than a runtime report from a state something has to reach first. Verified by pointing ICON_QUEUE at bookmark-check and watching it fail.
chrome.test.ts asserted ['check', 'bookmark', 'plus'] and so pinned the badge's glyphs against the vocabulary they were meant to follow — passing was the reason nobody looked. It names them from the table now and keeps the assertion that the three differ, which is the property the states actually need.
One reuse kept on purpose
The Downloads nav item stays the solid bookmark, which is also the badge's "requested". That is the same word twice, not two words — the badge says the entity is on your list and the nav item is that list. Changing it to download was the alternative and is churn on a nav icon to remove a coherence.
Answers #34 — Phase 1 item 3 of the roadmap (#73), and with #16 merged this leaves #38 unblocked.
## The survey
Every `<wa-icon>` with a label beside it, across `frontend/src`:
| meaning | before | after |
| --- | --- | --- |
| Play / Play Next | `play` / `forward-step` | unchanged |
| **Add to Queue** | `plus` ×5, `list` ×1 | `bars-staggered` |
| **Add to Playlist** | `plus` — *the same glyph, adjacent in the same menu* | `list` |
| **the queue itself** | `list` — *also the Playlists nav item* | `bars-staggered` |
| a playlist / Playlists nav | `list` | `list` |
| New Playlist, drop zones | `plus` | `plus` |
| **can be requested** | `plus` | `regular/bookmark` |
| requested | `bookmark` | `solid/bookmark` |
| in your library | `check` | unchanged |
`plus` carried four meanings, two of them side by side in one menu; `list` carried three.
## The rule
**An icon names the noun it acts on, not the verb.** "Add to queue" and "add to playlist" are one verb on two nouns, so the noun is what has to differ — which is why adding to a playlist wears the Playlists destination's own icon, and why the queue took `bars-staggered` and stopped wearing Playlists'. `plus` keeps the one thing it is unambiguous about.
`bars-staggered` is the only new glyph, confirmed present in Font Awesome **Free** 7.3.1 and vendored through `names.txt` + `fetch-icons.mjs`.
## Commits
| Commit | Issue |
| --- | --- |
| `refactor(ui): give the icons one vocabulary and sweep the call sites` | #34 |
## Two things this found rather than changed
- **The fix was already in the repo, unused.** `explore-album-details`'s "Request this" button has used the `regular/bookmark` → `solid/bookmark` pair since it was written, while the badge forty pixels away showed a **plus** for the same state. That is `utils/library-status.ts`'s fault one layer down: it made the two agree on what wanting *means* and left them disagreeing on what it looks like.
- **A live bug.** `explore-artist-details`'s Follow button was `bookmark-check` — Font Awesome **Pro**, never bundled — so it has drawn the missing-icon fallback, a circled question mark, for every followed artist since it was written. `requested-badge.spec.ts` exists for exactly this bug on the *album* button and says so in its docstring; this is the same bug one component over, still live, because `offline-icons.spec.ts` sweeps `__yjIconMisses` and no spec had ever followed an artist.
## Verification actually run
- `make ui-test` — **855 passed** (75 files), up from 854.
- `tsc --noEmit`, `css-literals`, `frontend-typecheck` clean.
- `icon-language.test.ts` — 11 specs. Two of them are the point:
- **it sweeps the source.** Reads every `src/**/*.ts` as raw text and fails on a governed name written outside the table — same shape as `TestNoDirectRuntimeEmits`, because the rule is about every call site and checking one checks nothing. Verified it fails by reintroducing one `name="plus"` in `track-list.ts` and watching it name the file.
- **it asserts every `ICON_*` is bundled**, which is what turns a Pro name into a failing test rather than a runtime report from a state something has to reach first. Verified by pointing `ICON_QUEUE` at `bookmark-check` and watching it fail.
- `chrome.test.ts` asserted `['check', 'bookmark', 'plus']` and so pinned the badge's glyphs *against* the vocabulary they were meant to follow — passing was the reason nobody looked. It names them from the table now and keeps the assertion that the three differ, which is the property the states actually need.
## One reuse kept on purpose
The Downloads nav item stays the solid bookmark, which is also the badge's "requested". That is the same word twice, not two words — the badge says the entity is on your list and the nav item is that list. Changing it to `download` was the alternative and is churn on a nav icon to remove a coherence.
Closes #34
`plus` meant "add to the queue", "add to a playlist", "make a new
playlist" and "you do not own this" -- the first two adjacent in the
same context menu, so two neighbouring items were the same glyph doing
different things. `list` meant the queue (the button that opens it), the
Playlists destination, and adding to the queue in `queue-panel` alone.
Two icons carrying seven meanings is not a vocabulary, and nothing
catches it: a wrong-but-real icon renders perfectly.
`utils/icon-language.ts` is the table, beside `library-status.ts` as the
issue suggested. The rule it is built on is that an icon names the
**noun** it acts on, not the verb: "add to queue" and "add to playlist"
are one verb on two nouns, so the noun is what differs -- which is why
adding to a playlist wears the Playlists destination's own icon, and why
the queue took `bars-staggered` and stopped wearing Playlists'. `plus`
keeps the one meaning it is unambiguous about, making something that is
not there yet, which covers New Playlist and the drop zones.
`bars-staggered` is the only new glyph, vendored through names.txt and
fetch-icons.mjs after confirming it is in Font Awesome **Free** 7.3.1.
Two things this found rather than changed:
- The request toggle's outline/solid pair was already in the app and
already right -- `explore-album-details`'s "Request this" button has
used `regular/bookmark` -> `solid/bookmark` since it was written --
while the badge forty pixels away showed a **plus** for the same
state. That is `utils/library-status.ts`'s fault one layer down: it
made the two surfaces agree on what wanting *means* and left them
disagreeing on what it looks like.
- `explore-artist-details`'s Follow button was `bookmark-check`, which
is Font Awesome **Pro** and has never been bundled, so it has drawn
the missing-icon fallback -- a circled question mark -- for every
followed artist since it was written. `requested-badge.spec.ts` was
written for exactly this bug on the album button and says so in its
docstring; this is the same bug one component over, still live,
because `offline-icons.spec.ts` sweeps `__yjIconMisses` and no spec
had ever followed an artist.
So the test does what reaching the state cannot. `icon-language.test.ts`
reads every `src/**/*.ts` as raw text and fails on a governed name
written outside the table, and separately asserts every `ICON_*` is a
*bundled* name -- which is what makes a Pro name a failing test rather
than a runtime report from a state something has to reach first. Its
first assertion is that it read any source at all, because a sweep over
an empty glob passes.
`chrome.test.ts` asserted `['check', 'bookmark', 'plus']` and so pinned
the badge's glyphs against the vocabulary they were meant to follow; it
names them from the table now, and keeps the assertion that the three
differ, which is the property the states actually need.
Downloads keeps the solid bookmark on purpose. That is one word twice,
not two words: the badge says the entity is on your list and the nav
item is that list.
Closes#34
logan
merged commit 065a879190 into main2026-08-19 01:37:34 +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.
Answers #34 — Phase 1 item 3 of the roadmap (#73), and with #16 merged this leaves #38 unblocked.
The survey
Every
<wa-icon>with a label beside it, acrossfrontend/src:play/forward-stepplus×5,list×1bars-staggeredplus— the same glyph, adjacent in the same menulistlist— also the Playlists nav itembars-staggeredlistlistplusplusplusregular/bookmarkbookmarksolid/bookmarkcheckpluscarried four meanings, two of them side by side in one menu;listcarried three.The rule
An icon names the noun it acts on, not the verb. "Add to queue" and "add to playlist" are one verb on two nouns, so the noun is what has to differ — which is why adding to a playlist wears the Playlists destination's own icon, and why the queue took
bars-staggeredand stopped wearing Playlists'.pluskeeps the one thing it is unambiguous about.bars-staggeredis the only new glyph, confirmed present in Font Awesome Free 7.3.1 and vendored throughnames.txt+fetch-icons.mjs.Commits
refactor(ui): give the icons one vocabulary and sweep the call sitesTwo things this found rather than changed
explore-album-details's "Request this" button has used theregular/bookmark→solid/bookmarkpair since it was written, while the badge forty pixels away showed a plus for the same state. That isutils/library-status.ts's fault one layer down: it made the two agree on what wanting means and left them disagreeing on what it looks like.explore-artist-details's Follow button wasbookmark-check— Font Awesome Pro, never bundled — so it has drawn the missing-icon fallback, a circled question mark, for every followed artist since it was written.requested-badge.spec.tsexists for exactly this bug on the album button and says so in its docstring; this is the same bug one component over, still live, becauseoffline-icons.spec.tssweeps__yjIconMissesand no spec had ever followed an artist.Verification actually run
make ui-test— 855 passed (75 files), up from 854.tsc --noEmit,css-literals,frontend-typecheckclean.icon-language.test.ts— 11 specs. Two of them are the point:src/**/*.tsas raw text and fails on a governed name written outside the table — same shape asTestNoDirectRuntimeEmits, because the rule is about every call site and checking one checks nothing. Verified it fails by reintroducing onename="plus"intrack-list.tsand watching it name the file.ICON_*is bundled, which is what turns a Pro name into a failing test rather than a runtime report from a state something has to reach first. Verified by pointingICON_QUEUEatbookmark-checkand watching it fail.chrome.test.tsasserted['check', 'bookmark', 'plus']and so pinned the badge's glyphs against the vocabulary they were meant to follow — passing was the reason nobody looked. It names them from the table now and keeps the assertion that the three differ, which is the property the states actually need.One reuse kept on purpose
The Downloads nav item stays the solid bookmark, which is also the badge's "requested". That is the same word twice, not two words — the badge says the entity is on your list and the nav item is that list. Changing it to
downloadwas the alternative and is churn on a nav icon to remove a coherence.Closes #34