feat(ui): a button over a picture answers the pointer with an accent ring

The media variant's hover darkened its body from 60 to 75% black, which no
one could see on a poster; a rail's scroll arrow over a card could not be told
from the card's own Play under it. Its hover is now a 2px accent ring over an
80% body (owner pick B), on every card control, Plex and YouTube, and the rail
arrows. DESIGN.md B3 names it beside the edged pills, with its log row.
This commit is contained in:
2026-10-09 00:27:28 +02:00
parent 4c7f73af9d
commit 600d5c39da
2 changed files with 11 additions and 5 deletions
+6 -3
View File
@@ -135,9 +135,11 @@ style guide.
- **State layers (B3):** hover and pressed are a layer, not a colour swap: the text colour mixed at **10%** - **State layers (B3):** hover and pressed are a layer, not a colour swap: the text colour mixed at **10%**
(hover) / **16%** (pressed) over whatever the control sits on, so it reads on the page, a card and glass (hover) / **16%** (pressed) over whatever the control sits on, so it reads on the page, a card and glass
alike. A filled control mixes its own text colour into its fill at 14% / 24%. Opacity dimming and alike. A filled control mixes its own text colour into its fill at 14% / 24%. Opacity dimming and
`bg-card` hovers are violations (invisible on a light card). Selected stays the solid accent. The one `bg-card` hovers are violations (invisible on a light card). Selected stays the solid accent. The
exception is an edged pill (a chip, a toolbar or form trigger, a segment): its hover is the accent edge exceptions are an edged pill (a chip, a toolbar or form trigger, a segment): its hover is the accent edge
(`.pill:hover`, `glass-hover`), which reads on every surface too (owner decision F14). (`.pill:hover`, `glass-hover`), which reads on every surface too (owner decision F14); and a dark
translucent button on a picture (the `media` variant: a card's hover row, a rail's scroll arrows, Restart),
whose hover is a 2px accent ring over a darker body, since a layer is lost in the picture.
A card that is one row with actions answers as a whole: the layer is the card's, under its badges and A card that is one row with actions answers as a whole: the layer is the card's, under its badges and
buttons, and the row's open button spans the card beneath the actions (a hover that stopped at the first buttons, and the row's open button spans the card beneath the actions (a hover that stopped at the first
badge read as broken; owner, E28 — `AdminUsers` user rows). badge read as broken; owner, E28 — `AdminUsers` user rows).
@@ -714,4 +716,5 @@ of a full-width panel and nothing on the right.
| 2026-10-08 | Captions on touch | A `Tooltip` opens for a mouse and a key's focus only, never for a finger | A caption on tap; a long-press caption | On an iPad the tap that showed the caption was taken as a hover and lost its click (every rail button took two taps), and no finger sends the mouseleave that hides it; the rail's labels setting names the buttons on touch | | 2026-10-08 | Captions on touch | A `Tooltip` opens for a mouse and a key's focus only, never for a finger | A caption on tap; a long-press caption | On an iPad the tap that showed the caption was taken as a hover and lost its click (every rail button took two taps), and no finger sends the mouseleave that hides it; the rail's labels setting names the buttons on touch |
| 2026-10-08 | Header search on touch | No key cap on a touch screen; the pill grows to 52 px so a ring shows round the 44 px Go; Go drops to its icon by the column's width | Keep the key cap; a 44 px Go overhanging a 40 px pill | On a tablet the 44 px key cap and Go sat on the pill's edge and cut the placeholder; an overhanging Go breaks the nested radii | | 2026-10-08 | Header search on touch | No key cap on a touch screen; the pill grows to 52 px so a ring shows round the 44 px Go; Go drops to its icon by the column's width | Keep the key cap; a 44 px Go overhanging a 40 px pill | On a tablet the 44 px key cap and Go sat on the pill's edge and cut the placeholder; an overhanging Go breaks the nested radii |
| 2026-10-08 | Plex subtitles and the control bar | The player draws the cues itself; while the bar shows they rise above it (200 ms), then settle back | The browser's own cues, moved by `line` | On an iPad the bar covered the text; a native cue cannot be animated or measured, and our layer behaves the same on every engine | | 2026-10-08 | Plex subtitles and the control bar | The player draws the cues itself; while the bar shows they rise above it (200 ms), then settle back | The browser's own cues, moved by `line` | On an iPad the bar covered the text; a native cue cannot be animated or measured, and our layer behaves the same on every engine |
| 2026-10-08 | Hover on a button over a picture | The `media` variant's hover is a 2px accent ring over a darker body (Plex + YT cards, rail arrows; option B) | An accent fill (reads as "selected"); a white wash (weak on a bright poster) | The 60 → 75% black step was invisible, and over a card a rail arrow could not be told from the card's own Play under it |
| 2026-10-08 | Plex "Add to collection" | A movie or show card's menu row opens a panel beside the card: its library's manual collections tick in place, a name + Enter creates one with the title in it (admin; option A) | An Add submenu with a "New…" dialog; the per-title editor modal from the menu | A collection took a trip to the Collections page, a name, a title search, then a second search per title; the panel is the video card's "Add to playlist" | | 2026-10-08 | Plex "Add to collection" | A movie or show card's menu row opens a panel beside the card: its library's manual collections tick in place, a name + Enter creates one with the title in it (admin; option A) | An Add submenu with a "New…" dialog; the per-title editor modal from the menu | A collection took a trip to the Collections page, a name, a title search, then a second search per title; the panel is the video card's "Add to playlist" |
+5 -2
View File
@@ -46,7 +46,10 @@ const BUTTON_VARIANTS: Record<ButtonVariant, string> = {
glass: "font-medium glass-card glass-hover act:hover:text-accent", glass: "font-medium glass-card glass-hover act:hover:text-accent",
// The player chrome is dark in the light theme too: a theme-fg state layer would be a dark wash. // The player chrome is dark in the light theme too: a theme-fg state layer would be a dark wash.
overlay: "font-medium text-white/80 act:hover:text-white act:hover:bg-white/15", overlay: "font-medium text-white/80 act:hover:text-white act:hover:bg-white/15",
media: "font-medium bg-black/60 text-white act:hover:bg-black/75", // On a picture a layer is lost in the picture's own light and dark: the hover is the accent edge
// (B3's edged-pill rule), a 2px ring over a darker body (owner pick B).
media:
"font-medium bg-black/60 text-white act:hover:bg-black/80 act:hover:ring-2 act:hover:ring-accent",
"danger-soft": "danger-soft":
"font-medium border border-danger/60 text-danger state-layer act:hover:border-danger", "font-medium border border-danger/60 text-danger state-layer act:hover:border-danger",
link: "font-semibold text-accent act:hover:underline", link: "font-semibold text-accent act:hover:underline",
@@ -112,7 +115,7 @@ const ICON_VARIANTS: Record<IconButtonVariant, string> = {
glass: "glass-card glass-hover act:hover:text-accent", glass: "glass-card glass-hover act:hover:text-accent",
// The player chrome and a thumbnail are dark in the light theme too, so these two paint with // The player chrome and a thumbnail are dark in the light theme too, so these two paint with
// white and black, not with the theme's fg (whose state layer would be a dark wash on a dark video). // white and black, not with the theme's fg (whose state layer would be a dark wash on a dark video).
media: "bg-black/60 text-white act:hover:bg-black/75", media: "bg-black/60 text-white act:hover:bg-black/80 act:hover:ring-2 act:hover:ring-accent",
overlay: "text-white/80 act:hover:text-white act:hover:bg-white/15", overlay: "text-white/80 act:hover:text-white act:hover:bg-white/15",
}; };