Skip to content

fix(tombstone): give the confirmation toast a readable backing - #259

Merged
moskovich merged 1 commit into
mainfrom
fix/3452-toast-legibility
Jul 29, 2026
Merged

fix(tombstone): give the confirmation toast a readable backing#259
moskovich merged 1 commit into
mainfrom
fix/3452-toast-legibility

Conversation

@moskovich

Copy link
Copy Markdown
Contributor

Closes #257. Independent of #258 — different files apart from one non-overlapping region in TombstoneOverlay.tsx, so either can merge first.

The bug

The FF1-side toast ("Tombstone set to 'On'") rendered white 12px text with only a textShadow behind it. Over a light artwork it was close to invisible, which means the confirmation failed at the one job it has.

The fix, and where the design came from

#257 asked for a design pass — scrim, pill, or adaptive contrast. It didn't need one, because ff-app already answers the question. lib/widgets/overlays/app_global_overlay_layer.dart styles every app toast as a card: solid black fill, 12px corner radius, 16/12 padding, white body text, two-layer drop shadow. This ports that treatment. The app and the wall should confirm things the same way, and a solid fill is legible over any artwork by construction rather than by tuning.

Type also goes to 16px-at-720, matching the label in TombstoneOverlay. 12px is below TV-distance legibility on a 1080p wall, and contrast does not fix a size problem.

Incidental cleanup

designPx moves into its own module. The label and the toast have to scale together, and the toast had the 720-canvas conversion duplicated as raw arithmetic. One definition, both importing it.

Verification

10 tombstone tests pass (6 existing, 4 new), tsc --noEmit clean, Prettier clean, production build succeeds.

TombstoneToast.test.tsx asserts the opaque fill directly rather than leaving legibility to a visual check, since the fill is the entire point of the fix. It also covers the dismiss window and its restart when a new confirmation arrives mid-window.

Not verified on a wall. What to look at on a device: whether a black card reads as belonging to the same family as the white tombstone label sitting below-left of it, and whether bottom-center is right — placement was never specified and is still an approximation, though it is now a visible object rather than floating text, so a wrong position is more obvious.

Not addressed

The toast's placement and the card's relationship to the white label are still unspecified anywhere. If B&F want something different they'll say so; this makes the feature work in the meantime rather than shipping an invisible confirmation into 1.0.22.

The FF1-side toast rendered white 12px text with only a text shadow behind it,
so it was close to invisible over light artworks — the confirmation failed at
exactly the job it exists to do.

Style it as a card, matching how ff-app presents its own toasts in
lib/widgets/overlays/app_global_overlay_layer.dart: solid black fill, 12px
corner radius, 16/12 padding, white body text, two-layer drop shadow. The app
and the wall should confirm things the same way.

Also raise the type to 16px-at-720, matching the label in TombstoneOverlay. A
12px line is below TV-distance legibility on a 1080p wall, and contrast does
not fix a size problem.

Extract designPx into its own module: the label and the toast have to scale
together, and the conversion was duplicated as raw arithmetic in the toast.

Adds TombstoneToast.test.tsx, which asserts the opaque fill rather than leaving
it to a visual check, plus the dismiss window and its restart on a new
confirmation.

Closes #257

@feralfile-bot feralfile-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewers: 2 (approve: 0, comment: 2, request-changes: 0).

  • Medium — The two independent reviews agree that the core display-facing behavior still lacks required manual wall/device smoke evidence. Unit tests verify inline styles and timer behavior, but not legibility, vh scaling, card bounds, or bottom-center placement at 1080p/4K. Please perform and record a smoke pass on the affected display route before handoff, per docs/verification.md and docs/review-workflow.md.

@moskovich

Copy link
Copy Markdown
Contributor Author

Verified in a real player render, and the before/after is not a matter of taste.

Method: built this branch, served the static export, drove headless Chromium at 1280×720 through the same window.handleCDPRequest contract feral-controld uses — displayPlaylist over a deliberately pale artwork, then a tombstone mode change to fire the confirmation. Same script against main for the before.

Measured in the toast region, glyph cores against their immediate surround:

contrast dark-pixel coverage
main 1.27:1 (glyph ~218, surround ~244) 0.0000
this branch 18.49:1 (glyph 0, surround ~240) 0.3586

At a luminance threshold of 140 the current toast has zero dark pixels anywhere in that region. Its darkest pixel is 218 out of 255. WCAG's floor for body text is 4.5:1 and this is 1.27:1, so over a pale work the confirmation is not "hard to read" — it is functionally absent. That matches what #257 reported from the wall.

The card also self-dismisses correctly; the frame 3.2s after the change is clean.

Two things the run surfaced, neither caused by this PR and neither worth fixing here:

A mode change on a fresh boot produces no toast at all. useTombstone only sets toast text when previousModeRef.current !== null, so the first updateDisplaySettings after a reload seeds the ref silently. Deliberate — it stops a toast firing on every startup — but it does mean the first tombstone change after a reboot is unconfirmed. Worth knowing before someone reports it as this PR's bug.

displayPlaylist returns ok: false with no error when intent.action is missing. Cost me a cycle. Not in scope, but a silent ok: false on a malformed cast is unfriendly to anyone casting by hand.

Still not verified on physical hardware. FF1-KKJW7J95 refuses SSH on 22, only its API port 1111 is up, so the bundle could not be sideloaded from here. Note this PR's file is the ff-player toast; the other loading overlay, ffos-user#243, is a separate static page in a different repo and is not covered by any of this.

@moskovich
moskovich merged commit 34e0f9f into main Jul 29, 2026
6 checks passed
@moskovich
moskovich deleted the fix/3452-toast-legibility branch July 29, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tombstone toast: illegible over light artworks — needs scrim/contrast design pass

2 participants