fix(plex): text over the picture sits on a dark panel
The player's loading, stall and error text was bare white or red on the video, unreadable over a bright frame. It now sits on the dark panel the subtitle notice and the track OSD already used, one constant for all three. DESIGN.md records it and the slow-connection line.
This commit is contained in:
@@ -568,6 +568,9 @@ of a full-width panel and nothing on the right.
|
||||
the first tap however long the video played).
|
||||
- **The bars stay up while the pointer rests on them** (F22, owner); leaving starts a fresh 3 s. YouTube and
|
||||
Plex Web do the same: before, the row faded out from under a mouse parked on Next.
|
||||
- **Text over the picture sits on a dark panel** (2026-11-07): loading, stalls, errors and the notices are
|
||||
readable on any frame. A stall that lasts 5 s on a link measured slower than the stream says "Slow
|
||||
connection" with both rates.
|
||||
- **Volume is the native `Slider`** (A6); the hand-drawn bar had no hover, focus, keyboard or screen-reader
|
||||
state. A pointer drag gives the focus back, so Space and the arrows keep driving the player.
|
||||
- **The seek bar:** the track stays thin inside a 2.75rem (44px) hit area with `touch-action: none`, so a finger
|
||||
@@ -870,3 +873,5 @@ of a full-width panel and nothing on the right.
|
||||
| 2026-11-06 | A pick in the open fold closes it (owner a) | Toggling a chip inside the "+N" popover closes the popover; the focus goes with the chip | Keep the popover open and focus the chip now in the picked one's place | The focus never sits outside a popover left open, and a picked chip leads the row anyway |
|
||||
| 2026-11-06 | An expired share link offers no Copy (owner a) | An expired row in the share dialog has a warn badge "expired <date>" and its address struck through; Open and Revoke stay, Copy goes | The warn badge alone, Copy kept | An expired link opens nothing, so it is no link to hand out; Open still lets the owner check it |
|
||||
| 2026-11-06 | The shared page's unlock button is a noun in Hungarian (owner a) | "Megtekintés" for a video, "Megnyitás" for a file or folder | Both verbs, "Megnézem" / "Megnyitom" | The app's Hungarian buttons are nouns; one button should not change grammatical form by link kind |
|
||||
| 2026-11-07 | A slow link says so, with both rates (owner b1) | After 5 s of stalling on a link measured slower than the stream: "Slow connection" and "This file needs about X, about Y is arriving" under the spinner; no number measured, no claim | The line without numbers; a pill at the bottom | The viewer can tell their connection from a broken player, and by how much it falls short |
|
||||
| 2026-11-07 | Text over the picture sits on a dark panel (owner a) | The player's loading, stall and error text, the subtitle notice and the track OSD sit on one dark panel (`OVER_VIDEO`, black 75 %, a white 15 % edge) | A shadow behind the letters; bare text as before | Bare white or red text was unreadable over a bright frame (seen live); the panel is the style the notices already had |
|
||||
|
||||
@@ -118,6 +118,10 @@ const BACK_TO_PREV_S = 3;
|
||||
const PLAYER_MENU =
|
||||
"rounded-xl border border-white/15 bg-media-chrome/95 media-marks text-sm text-white shadow-2xl";
|
||||
const PLAYER_ROW = "block w-full rounded-lg px-2 py-1.5 text-left hover:bg-white/10";
|
||||
// Text over the picture (the loading/stall/error overlay, the subtitle notice, the track OSD) sits on
|
||||
// its own dark panel: bare white or red text was unreadable over a bright frame (measured live on a
|
||||
// white-lit scene). The shape (pill or panel) is each site's own.
|
||||
const OVER_VIDEO = "border border-white/15 bg-black/75 text-white shadow-2xl";
|
||||
// A track choice: white like the rest, the chosen one marked by the tick in the leading slot (DESIGN
|
||||
// "one of several"), which `media-marks` paints the media amber — a light theme's accent as the
|
||||
// label's colour was dark on the chrome (Slate 2.84:1), and the highlight's white washed it out.
|
||||
@@ -1328,9 +1332,11 @@ export default function PlexPlayer({
|
||||
className="absolute inset-0 grid place-items-center px-6 text-center text-sm pointer-events-none"
|
||||
>
|
||||
{loadError ? (
|
||||
<span className="max-w-md text-danger">{loadError}</span>
|
||||
<div className={`max-w-md rounded-xl px-4 py-3 ${OVER_VIDEO}`}>
|
||||
<span className="text-danger">{loadError}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-3 text-white/80">
|
||||
<div className={`flex flex-col items-center gap-3 rounded-xl px-5 py-4 ${OVER_VIDEO}`}>
|
||||
<Loader2 className="w-10 h-10 animate-spin" aria-hidden />
|
||||
{/* Announce the stall to assistive tech. Initial load shows visible text; a mid-playback
|
||||
rebuffer/seek (ready, no error) has no visible label, so give it an sr-only one via the
|
||||
@@ -1338,7 +1344,7 @@ export default function PlexPlayer({
|
||||
{slowRates ? (
|
||||
<>
|
||||
<span>{t("plex.player.slowLink")}</span>
|
||||
<span className="text-xs text-white/60">
|
||||
<span className="text-xs text-white/70">
|
||||
{t("plex.player.slowLinkRates", {
|
||||
need: formatMbps(slowRates.need, i18n.language),
|
||||
got: formatMbps(slowRates.got, i18n.language),
|
||||
@@ -1369,7 +1375,9 @@ export default function PlexPlayer({
|
||||
aria-live="polite"
|
||||
>
|
||||
{selectedSub && subNotice && (
|
||||
<div className="flex max-w-full items-center gap-2 truncate rounded-full border border-white/15 bg-black/75 px-4 py-2 text-sm text-white shadow-2xl">
|
||||
<div
|
||||
className={`flex max-w-full items-center gap-2 truncate rounded-full px-4 py-2 text-sm ${OVER_VIDEO}`}
|
||||
>
|
||||
{subNotice !== "preparing" ? (
|
||||
<span className="text-danger">{t(`plex.player.subUnavailable.${subNotice}`)}</span>
|
||||
) : (
|
||||
@@ -1395,7 +1403,7 @@ export default function PlexPlayer({
|
||||
aria-live="polite"
|
||||
>
|
||||
{osd && (
|
||||
<div className="max-w-full truncate rounded-full border border-white/15 bg-black/75 px-4 py-2 text-sm text-white shadow-2xl">
|
||||
<div className={`max-w-full truncate rounded-full px-4 py-2 text-sm ${OVER_VIDEO}`}>
|
||||
{osd}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user