Legible per-source error banner - #68
Open
trevormunoz wants to merge 1 commit into
Open
trevormunoz wants to merge 1 commit into
trevormunoz wants to merge 1 commit into
Conversation
The player's failure banner showed the raw technical error.message
(e.g. "HLS error: networkError") for every error, so a viewer had no
idea a fatal load failure — like an upstream manifest/media 5xx — came
from the source being unreachable. It now shows a short, source-keyed
message instead.
- Thread the error source onto player state via a setError(error, source)
funnel on PlayerStateManager; every error site (Root manifest/canvas/
auth/media, Viewer native/HLS/DASH, PlayerState playback) sets it.
- resolveErrorMessageKeys maps the source to new, translatable TermKeys:
manifest/canvas -> "This item couldn't be loaded." media -> "This media
couldn't be played." auth -> "Sign-in required." — each with a neutral
cause line that makes no (mis)claim about the failure being temporary.
Non-fatal errors still render, with a generic friendly message.
- The banner is role="status" (polite), not assertive alert, and carries
part="error"; the element gives it a default-styled panel via
::part(error) and --iiif-player-error-fg/-bg (contrast 5.45:1, added to
the TOKEN_CONTRAST_PAIRS guard). The compound Root stays unstyled.
Behavior change: the banner's role (alert -> status) and copy (raw ->
friendly) are observable. Hosts that drove their own error UI can hide
the panel with `::part(error){display:none}` and keep using
iiif-player-error / errorCallback.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D2MtErpTjB6bWPrn3EnCgV
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The player's failure banner rendered the raw technical
error.message(e.g.HLS error: networkError, or a bare fetch error) for every error. During a real upstream outage that reads as noise — a viewer can't tell the source is unreachable. This replaces it with a short, source-keyed message.setError(error, source)funnel onPlayerStateManagerrecords the error source alongside the error. Every existing error site routes through it — Root (manifest/canvas/auth/media), Viewer (native/HLS/DASH), PlayerState (playback) — with no change to theiiif-player-error/errorCallbackpayloads.resolveErrorMessageKeys(source)maps the source to new, translatableTermKeys:manifest/canvas→ "This item couldn't be loaded.",media→ "This media couldn't be played.",auth→ "Sign-in required." — each with a neutral cause line (no "temporarily" claim, since failures include permanent ones). Non-fatal errors (e.g. a blockedplay()) still render, with a generic friendly message.role="status"(polite) withpart="error". The compoundRootstays visually unstyled; the element gives the part a default-styled panel via::part(error)and--iiif-player-error-fg/--iiif-player-error-bg.Behavior change (observable)
role:alert→status.error.message→ friendly per-source copy.A host that drove its own error UI off the old banner can hide the default with
iiif-transcript-player::part(error) { display: none }and keep usingiiif-player-error/errorCallback. Documented in the README.Accessibility
#b91c1con#fbeae8= 5.45:1) and added to theTOKEN_CONTRAST_PAIRSguard. An earlier draft usedopacity: 0.85on the detail line — that computed to 4.44:1 and the axe suite caught it; opacity removed.role="status"chosen overalert: a failed load is informational, not an interrupt.Out of scope
No retry button (recovery is replacing the element, as documented); no raw/HTTP detail line in the default (a host can render it via
::part(error)); no auth login flow (a host adds a sign-in link).Testing
resolveErrorMessageKeys; newPlayerStateManagersetError/clearErrortest.::part(error)reachability test;element-errors/Rootbanner tests updated forrole="status"and the friendly copy.Relates to the
<iiif-transcript-player>element surface (#61).🤖 Generated with Claude Code
https://claude.ai/code/session_01D2MtErpTjB6bWPrn3EnCgV