feat(replay): HC-mode coverage for keybind-footer top border
Tag the footer's border-carrying Node with `HighContrastBorder::with_default(BORDER_SUBTLE)` so the existing `apply_high_contrast_borders` system bumps the 1 px top border from `BORDER_SUBTLE` (#505050) to `BORDER_SUBTLE_HC` (#a0a0a0) when `Settings::high_contrast_mode` is on. Without this the footer reads as floating loose under HC because the border that visually anchors it to the labels row above is near-invisible at #505050 against the elevated banner background. The footer's text colours (`TEXT_SECONDARY` on both the mode-line and the hint) don't need an HC bump — `TEXT_SECONDARY` is already at `#a0a0a0`, the same luminance as `BORDER_SUBTLE_HC`. There's no `TEXT_SECONDARY_HC` constant in the palette because secondary text is already at HC-border level by design. The notch labels also use `TEXT_SECONDARY` and inherit the same "already HC-bright" property — no marker needed there either. The 1 px scrub track, notch ticks, and WIN MOVE marker render via `BackgroundColor` (not `BorderColor`) so the `HighContrastBorder` marker doesn't apply. HC coverage for those decorative pieces would need a custom settings-aware paint system (precedent: `radial_rim_outline` in `radial_menu`) and is deferred to a follow-up commit. 1 new test pinning the marker on spawn. 1243 → 1244. Clippy clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -35,8 +35,9 @@ use crate::replay_playback::{
|
|||||||
use solitaire_data::ReplayMove;
|
use solitaire_data::ReplayMove;
|
||||||
use crate::ui_modal::{spawn_modal_button, ButtonVariant};
|
use crate::ui_modal::{spawn_modal_button, ButtonVariant};
|
||||||
use crate::ui_theme::{
|
use crate::ui_theme::{
|
||||||
ACCENT_PRIMARY, BG_ELEVATED_HI, BORDER_SUBTLE, STATE_SUCCESS, TEXT_PRIMARY, TEXT_SECONDARY,
|
ACCENT_PRIMARY, BG_ELEVATED_HI, BORDER_SUBTLE, HighContrastBorder, STATE_SUCCESS, TEXT_PRIMARY,
|
||||||
TYPE_BODY, TYPE_CAPTION, TYPE_HEADLINE, VAL_SPACE_1, VAL_SPACE_2, VAL_SPACE_4, Z_DROP_OVERLAY,
|
TEXT_SECONDARY, TYPE_BODY, TYPE_CAPTION, TYPE_HEADLINE, VAL_SPACE_1, VAL_SPACE_2, VAL_SPACE_4,
|
||||||
|
Z_DROP_OVERLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -680,6 +681,14 @@ fn spawn_overlay(
|
|||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
BorderColor::all(BORDER_SUBTLE),
|
BorderColor::all(BORDER_SUBTLE),
|
||||||
|
// Marker for `apply_high_contrast_borders`: bumps
|
||||||
|
// the 1 px top border from BORDER_SUBTLE (#505050)
|
||||||
|
// to BORDER_SUBTLE_HC (#a0a0a0) when
|
||||||
|
// `Settings::high_contrast_mode` is on. Without
|
||||||
|
// this the footer reads as floating loose under
|
||||||
|
// HC because the border that visually anchors it
|
||||||
|
// to the labels row above is near-invisible.
|
||||||
|
HighContrastBorder::with_default(BORDER_SUBTLE),
|
||||||
))
|
))
|
||||||
.with_children(|footer| {
|
.with_children(|footer| {
|
||||||
footer.spawn((
|
footer.spawn((
|
||||||
@@ -2008,6 +2017,34 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawned footer carries `HighContrastBorder` so the existing
|
||||||
|
/// `apply_high_contrast_borders` system bumps the 1 px top
|
||||||
|
/// border under HC mode. Without this the footer reads as
|
||||||
|
/// floating loose under HC.
|
||||||
|
#[test]
|
||||||
|
fn keybind_footer_carries_high_contrast_border_marker() {
|
||||||
|
let mut app = headless_app();
|
||||||
|
set_state(
|
||||||
|
&mut app,
|
||||||
|
ReplayPlaybackState::Playing {
|
||||||
|
replay: synthetic_replay(10),
|
||||||
|
cursor: 0,
|
||||||
|
secs_to_next: 0.5,
|
||||||
|
paused: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
app.update();
|
||||||
|
|
||||||
|
let mut q = app
|
||||||
|
.world_mut()
|
||||||
|
.query_filtered::<&HighContrastBorder, With<ReplayOverlayKeybindFooter>>();
|
||||||
|
let marker = q.iter(app.world()).next();
|
||||||
|
assert!(
|
||||||
|
marker.is_some(),
|
||||||
|
"footer must carry HighContrastBorder so `apply_high_contrast_borders` picks it up under HC mode",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Footer shares the overlay tree's lifecycle — it despawns on
|
/// Footer shares the overlay tree's lifecycle — it despawns on
|
||||||
/// `Playing → Inactive` along with the banner root.
|
/// `Playing → Inactive` along with the banner root.
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user