refactor(ui): give the icons one vocabulary and sweep the call sites
`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
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* What each icon in this app means, once.
|
||||
*
|
||||
* The set was a mix: `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* — while `list` meant
|
||||
* the queue, the Playlists destination, and (in `queue-panel` alone)
|
||||
* adding to the queue. Two icons carrying seven meanings between them
|
||||
* is not a vocabulary, and a user cannot learn one that says four
|
||||
* things.
|
||||
*
|
||||
* The rule these are chosen by: **an icon names the noun it acts on,
|
||||
* not the verb.** "Add to queue" and "add to playlist" are the same
|
||||
* verb on different nouns, so the noun is what has to differ — which is
|
||||
* also why adding to a playlist wears the Playlists destination's own
|
||||
* icon rather than a generic plus. `plus` survives for exactly the one
|
||||
* thing it is unambiguous about, making something that did not exist.
|
||||
*
|
||||
* Import these rather than writing a name inline. A literal string is
|
||||
* how the last set drifted, and nothing catches it: a wrong-but-real
|
||||
* icon renders perfectly.
|
||||
*/
|
||||
|
||||
/** Start playing this now. */
|
||||
export const ICON_PLAY = 'play';
|
||||
|
||||
/** Start playing this now, in a shuffled order. */
|
||||
export const ICON_SHUFFLE = 'shuffle';
|
||||
|
||||
/**
|
||||
* The queue, and putting something into it.
|
||||
*
|
||||
* One glyph for the noun and the action, so the button that opens the
|
||||
* queue and the menu item that adds to it are visibly the same subject.
|
||||
* The queue used to wear `list`, which is the Playlists destination.
|
||||
*/
|
||||
export const ICON_QUEUE = 'bars-staggered';
|
||||
|
||||
/** Put this next in the queue rather than at the end. */
|
||||
export const ICON_PLAY_NEXT = 'forward-step';
|
||||
|
||||
/**
|
||||
* A playlist, and adding something to one.
|
||||
*
|
||||
* The same icon as the Playlists destination in the sidebar, which is
|
||||
* the point: the menu item says where the thing is going.
|
||||
*/
|
||||
export const ICON_PLAYLIST = 'list';
|
||||
|
||||
/**
|
||||
* Make a new thing that did not exist — a playlist, a rule, a library.
|
||||
*
|
||||
* This is the only meaning `plus` keeps. It used to carry four.
|
||||
*/
|
||||
export const ICON_NEW = 'plus';
|
||||
|
||||
/**
|
||||
* The request ("want") toggle, as an outline/solid pair.
|
||||
*
|
||||
* Two states of one control have to read as each other's opposite,
|
||||
* which a plus and a bookmark do not. The pair was already in the app
|
||||
* and already correct — `explore-album-details`'s "Want this" button
|
||||
* has used it since it was written, and `favorites-controller` uses the
|
||||
* same shape for `regular/heart` → `heart` — 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.
|
||||
*/
|
||||
export const ICON_CAN_REQUEST = 'regular/bookmark';
|
||||
export const ICON_REQUESTED = 'solid/bookmark';
|
||||
|
||||
/**
|
||||
* You have this.
|
||||
*
|
||||
* Deliberately not drawn on the common case — see the tracklist, where
|
||||
* absence is what gets marked. This is for the places that answer the
|
||||
* question directly, like the badge on a catalog card.
|
||||
*/
|
||||
export const ICON_IN_LIBRARY = 'check';
|
||||
|
||||
/**
|
||||
* Something is being fetched right now.
|
||||
*
|
||||
* Distinct from `ICON_REQUESTED`: a request may sit on the list
|
||||
* forever without anything happening, which is exactly why the badge's
|
||||
* "queued" state stopped being an hourglass.
|
||||
*/
|
||||
export const ICON_DOWNLOADING = 'download';
|
||||
|
||||
/**
|
||||
* Take this away.
|
||||
*
|
||||
* One icon for removing from a playlist, from the queue and from the
|
||||
* library, because the difference that matters is stated in the words
|
||||
* beside it and in the confirmation — "Remove from Library" says in its
|
||||
* impact line that the files are not deleted.
|
||||
*/
|
||||
export const ICON_REMOVE = 'trash';
|
||||
Reference in New Issue
Block a user