fix(player): the Plex player's fills hold on its chrome: an amber head on a white played part

A light theme's accent as a fill on the always-dark chrome was ~2.8:1 (Slate), under the 3:1 a
control needs. A native checkbox and slider tint with `accent-chosen` (the accent elsewhere, the
media amber under `media-marks`), and so does the skip button's countdown. The progress bar plays
white with an amber head: amber there marks a place, as the intro / credits markers do, and an amber
played part made a marker ahead of the head read as already played (owner's choice of three).
This commit is contained in:
2026-10-10 22:56:09 +02:00
parent 93192dadd8
commit 663a7e8012
4 changed files with 27 additions and 8 deletions
+7 -4
View File
@@ -1429,12 +1429,12 @@ export default function PlexPlayer({ itemId, onClose, queue, fromStart = false }
<>
{/* draining fill across the whole button… */}
<span
className="absolute inset-y-0 left-0 bg-accent/50"
className="absolute inset-y-0 left-0 bg-chosen/50"
style={{ width: `${skipProgress * 100}%` }}
/>
{/* …plus a crisp bottom bar so the countdown is unmistakable */}
<span
className="absolute bottom-0 left-0 h-1 bg-accent"
className="absolute bottom-0 left-0 h-1 bg-chosen"
style={{ width: `${skipProgress * 100}%` }}
/>
</>
@@ -1542,13 +1542,16 @@ export default function PlexPlayer({ itemId, onClose, queue, fromStart = false }
}}
/>
))}
{/* The played part white, the head the media amber: amber is a marked place on
the chrome (the head, the markers above), and an amber played part made a
marker ahead of the head read as already played. */}
<div
className="absolute inset-y-0 left-0 bg-accent rounded-full"
className="absolute inset-y-0 left-0 bg-white rounded-full"
style={{ width: `${headPct}%` }}
/>
{/* The head: on hover for a mouse, always on touch (C3), where nothing hovers. */}
<div
className={`absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-3 h-3 rounded-full bg-accent transition-opacity ${
className={`absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-3 h-3 rounded-full bg-media-mark transition-opacity ${
scrub != null
? "opacity-100"
: "opacity-0 group-hover:opacity-100 [@media(hover:none)]:opacity-100"
@@ -2,7 +2,8 @@ import clsx from "clsx";
import type { InputHTMLAttributes, ReactNode, Ref } from "react";
// A6 (docs/DESIGN.md): checkbox, slider and colour well are the BROWSER's controls, tinted
// with the accent — keyboard, screen reader and forced-colours support come free, and a drawn copy
// with the chosen colour (the accent; the media amber on the player chrome) — keyboard, screen
// reader and forced-colours support come free, and a drawn copy
// would have to rebuild all three. What the browser does not give is the 44 touch target: the labelled
// row (`CheckRow`) or the slider's own box grows to it on a coarse pointer. Like `Input`, a raw
// `<input>` for any of them anywhere else is a lint error.
@@ -22,7 +23,7 @@ export function Checkbox({
type="checkbox"
onChange={(e) => onChange?.(e.target.checked)}
className={clsx(
"size-4 shrink-0 cursor-pointer accent-accent disabled:cursor-not-allowed",
"size-4 shrink-0 cursor-pointer accent-chosen disabled:cursor-not-allowed",
className,
)}
{...rest}
@@ -70,7 +71,7 @@ export function Slider({
type="range"
onChange={(e) => onChange(Number(e.target.value))}
className={clsx(
"min-h-6 w-full cursor-pointer accent-accent pointer-coarse:min-h-(--touch-target)",
"min-h-6 w-full cursor-pointer accent-chosen pointer-coarse:min-h-(--touch-target)",
className,
)}
{...rest}