Three controls in the app are revealed by :hover and are the only
route to their action, so on a device without hover the action is gone —
and, being visibility: hidden / opacity: 0 rather than display: none, they are invisible controls that still take taps. #137
turned them up in #68's sweep and left them out of it, because the fix is
the opposite one.
What changed, and why
Two are always visible where the device has no hover, under @media not all and (hover: hover):
track-details — .cover-art-overlay / .cover-art-remove, the only
route to changing or removing a track's cover art.
shortcut-capture — .reset-btn, the only way to put a rebound
shortcut back.
The queue row's remove takes #68's treatment instead, which is what
the issue's own Sequencing paragraph asks for once #60 has landed: the
row's context menu is a bottom sheet now and carries "Remove from
Queue", so the button is redundant on touch rather than missing, and an
always-visible X would spend part of a 424px row on something one
long-press away. It is display: none outside (hover: hover) and (pointer: fine) — not visibility: hidden, which
would keep the hit area and the accessibility-tree entry for a control
the phone can never see.
Not extracted into styles/. That leaves two call sites of the
always-visible form (three selectors), under the four the issue names as
the threshold.
Verification
make ui-test — 988 passed, 6 of them hover-affordance.test.ts
(three new cases). The three were watched failing on the pre-fix
build.
Measured in a real engine at both media states, against make dev-headless, because no tier here can render as a touch device
(CDP's Emulation.setEmulatedMedia does not reach the component
tier's iframe, and the e2e projects are Desktop Chrome and Desktop
Safari):
control
touch context, 424x439
hover context, 1100x760
.remove-button
display: none
display: flex; visibility: hidden
.cover-art-overlay
opacity: 1
opacity: 0
.cover-art-remove
opacity: 1
opacity: 0
.reset-btn
opacity: 1
opacity: 0
Screenshots of track-details in edit mode, touch and hover, with
and without art: the pencil overlay and the × are on screen on touch
and invisible on the desktop.
npx tsc --noEmit, make css-check, make skill-check — clean.
Deliberately not done
No e2e spec. The suite's two projects have no touch, so a spec
there could only assert the desktop half, which the component tier
already pins. Adding a touch project is infrastructure this issue did
not ask for.
No device tier. Chrome 113 has both (hover: hover) and not all and (...), so this is nowhere near its documented gaps, but
it is unverified on the phone.
## What the issue was
Three controls in the app are revealed by `:hover` and are the **only**
route to their action, so on a device without hover the action is gone —
and, being `visibility: hidden` / `opacity: 0` rather than
`display: none`, they are invisible controls that still take taps. #137
turned them up in #68's sweep and left them out of it, because the fix is
the opposite one.
## What changed, and why
**Two are always visible where the device has no hover**, under
`@media not all and (hover: hover)`:
- `track-details` — `.cover-art-overlay` / `.cover-art-remove`, the only
route to changing or removing a track's cover art.
- `shortcut-capture` — `.reset-btn`, the only way to put a rebound
shortcut back.
**The queue row's remove takes #68's treatment instead**, which is what
the issue's own Sequencing paragraph asks for once #60 has landed: the
row's context menu is a bottom sheet now and carries "Remove from
Queue", so the button is redundant on touch rather than missing, and an
always-visible X would spend part of a 424px row on something one
long-press away. It is `display: none` outside
`(hover: hover) and (pointer: fine)` — not `visibility: hidden`, which
would keep the hit area and the accessibility-tree entry for a control
the phone can never see.
**Not extracted into `styles/`.** That leaves two call sites of the
always-visible form (three selectors), under the four the issue names as
the threshold.
## Verification
- **`make ui-test`** — 988 passed, 6 of them `hover-affordance.test.ts`
(three new cases). The three were **watched failing** on the pre-fix
build.
- **Measured in a real engine at both media states**, against
`make dev-headless`, because no tier here can render as a touch device
(CDP's `Emulation.setEmulatedMedia` does not reach the component
tier's iframe, and the e2e projects are Desktop Chrome and Desktop
Safari):
| control | touch context, 424x439 | hover context, 1100x760 |
|---|---|---|
| `.remove-button` | `display: none` | `display: flex; visibility: hidden` |
| `.cover-art-overlay` | `opacity: 1` | `opacity: 0` |
| `.cover-art-remove` | `opacity: 1` | `opacity: 0` |
| `.reset-btn` | `opacity: 1` | `opacity: 0` |
- **Screenshots** of `track-details` in edit mode, touch and hover, with
and without art: the pencil overlay and the × are on screen on touch
and invisible on the desktop.
- `npx tsc --noEmit`, `make css-check`, `make skill-check` — clean.
## Deliberately not done
- **No e2e spec.** The suite's two projects have no touch, so a spec
there could only assert the desktop half, which the component tier
already pins. Adding a touch project is infrastructure this issue did
not ask for.
- **No device tier.** Chrome 113 has both `(hover: hover)` and
`not all and (...)`, so this is nowhere near its documented gaps, but
it is unverified on the phone.
- **The `styles/` extraction**, per the threshold above.
Closes #137
CI is green on `5fbe1d9` (run 17395): `check` **success**, `e2e` **success** — the latter covering both Chromium and WebKit.
Not merging; leaving `Status/In Progress` on #137.
Three controls are revealed by :hover and are the only route to their
action on a device that has none. #68 hid the home card's play button on
touch, which was right because tapping the card does the same thing;
these are the opposite case, so hiding them removes the action outright
and leaving them costs the same long-press flash #68 was filed for --
they are visibility:hidden / opacity:0, so on touch they are invisible
controls that still take taps.
track-details' cover-art overlay and remove, and shortcut-capture's
reset, are always visible under `@media not all and (hover: hover)`.
The queue row's remove is the third case the report names and takes the
other treatment, because #60 has since landed: the row's context menu is
a bottom sheet carrying "Remove from Queue", so the action is one
long-press away and an always-visible X would spend part of a 424px row
on something already reachable. It is display:none outside
`(hover: hover) and (pointer: fine)` rather than visibility:hidden,
which would leave a button holding its hit area and its place in the
accessibility tree -- the trap this issue is about.
The rule is not extracted into styles/ yet: that leaves two call sites
of the always-visible form, under the four the report names.
No tier here can render as a touch device, so the tests read the parsed
stylesheet the way #68's does and say so; the touch and hover renderings
were measured against the running app in a hasTouch context instead.
Closes#137
Always-visible is not the same as always-in-the-way: the overlay is inset:0 at 50% black, so gating it on hover left every touch device with the artwork it is editing permanently darkened. It is only a hint — .cover-art-edit carries the click, so tapping the art always worked — while the × really is the only route to its action and stays. The chip borrows the remove button's size, disc and alpha.
Also corrects the claim that no tier can render as a touch device: no committed one does, which is a choice about projects rather than a limit.
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.
What the issue was
Three controls in the app are revealed by
:hoverand are the onlyroute to their action, so on a device without hover the action is gone —
and, being
visibility: hidden/opacity: 0rather thandisplay: none, they are invisible controls that still take taps. #137turned them up in #68's sweep and left them out of it, because the fix is
the opposite one.
What changed, and why
Two are always visible where the device has no hover, under
@media not all and (hover: hover):track-details—.cover-art-overlay/.cover-art-remove, the onlyroute to changing or removing a track's cover art.
shortcut-capture—.reset-btn, the only way to put a reboundshortcut back.
The queue row's remove takes #68's treatment instead, which is what
the issue's own Sequencing paragraph asks for once #60 has landed: the
row's context menu is a bottom sheet now and carries "Remove from
Queue", so the button is redundant on touch rather than missing, and an
always-visible X would spend part of a 424px row on something one
long-press away. It is
display: noneoutside(hover: hover) and (pointer: fine)— notvisibility: hidden, whichwould keep the hit area and the accessibility-tree entry for a control
the phone can never see.
Not extracted into
styles/. That leaves two call sites of thealways-visible form (three selectors), under the four the issue names as
the threshold.
Verification
make ui-test— 988 passed, 6 of themhover-affordance.test.ts(three new cases). The three were watched failing on the pre-fix
build.
Measured in a real engine at both media states, against
make dev-headless, because no tier here can render as a touch device(CDP's
Emulation.setEmulatedMediadoes not reach the componenttier's iframe, and the e2e projects are Desktop Chrome and Desktop
Safari):
.remove-buttondisplay: nonedisplay: flex; visibility: hidden.cover-art-overlayopacity: 1opacity: 0.cover-art-removeopacity: 1opacity: 0.reset-btnopacity: 1opacity: 0Screenshots of
track-detailsin edit mode, touch and hover, withand without art: the pencil overlay and the × are on screen on touch
and invisible on the desktop.
npx tsc --noEmit,make css-check,make skill-check— clean.Deliberately not done
there could only assert the desktop half, which the component tier
already pins. Adding a touch project is infrastructure this issue did
not ask for.
(hover: hover)andnot all and (...), so this is nowhere near its documented gaps, butit is unverified on the phone.
styles/extraction, per the threshold above.Closes #137
CI is green on
5fbe1d9(run 17395):checksuccess,e2esuccess — the latter covering both Chromium and WebKit.Not merging; leaving
Status/In Progresson #137.5fbe1d9923to3a47070d3f003610b7a3tod78830aa52