From cc635328be4a37710d603aae33bd4df12a15ffc4 Mon Sep 17 00:00:00 2001 From: funman300 Date: Wed, 6 May 2026 05:54:34 +0000 Subject: [PATCH] fix(engine): popover rows stay visible regardless of action-bar fade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quat: opening Modes / Menu showed a solid dark-purple block in the top-right with no readable content. Cause: the auto-fade system on the top-level action bar was fading the popover rows too — they share the `ActionButton` marker so `paint_action_buttons` can still paint hover/press, but `apply_action_fade` matched the same marker and dropped their alpha to whatever the cursor-position-based fade happened to be (typically 0 because the cursor was inside the opened popover, well below the top reveal zone). The popover container stayed at full opacity (its background is `BG_ELEVATED`, not driven by the fade), so what the player saw was the empty rounded box with no labels. Fix: new `PopoverRow` marker on the rows in `spawn_modes_popover` and `spawn_menu_popover` (both share the same row-spawn shape). `apply_action_fade` excludes `PopoverRow` via `Without`. Hover / press paint still applies — the popover rows just opt out of the cursor-position auto-fade since they only render when the player has explicitly opened the dropdown. Co-Authored-By: Claude Opus 4.7 (1M context) --- solitaire_engine/src/hud_plugin.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/solitaire_engine/src/hud_plugin.rs b/solitaire_engine/src/hud_plugin.rs index 997532e..b270e5d 100644 --- a/solitaire_engine/src/hud_plugin.rs +++ b/solitaire_engine/src/hud_plugin.rs @@ -206,6 +206,16 @@ pub const SCORE_FLOATER_THRESHOLD: i32 = 50; #[derive(Component, Debug)] pub struct ActionButton; +/// Marker on rows inside a popover panel ([`ModesPopover`] or +/// [`MenuPopover`]). Popover rows already carry `ActionButton` so the +/// hover/press paint path applies to them, but the auto-fade applied +/// to the top-level action bar must NOT also fade these rows — the +/// popover only renders when the player has explicitly opened it, so +/// its content should always be at full opacity. `apply_action_fade` +/// excludes entities with this marker via `Without`. +#[derive(Component, Debug)] +pub struct PopoverRow; + /// Marker on the "New Game" action button anchored top-right of the play /// area. Click fires [`NewGameRequestEvent`]; the existing /// `ConfirmNewGameScreen` modal handles confirmation when a game is in @@ -856,6 +866,7 @@ fn spawn_modes_popover( .spawn(( option, ActionButton, + PopoverRow, Button, Tooltip::new(tooltip), Node { @@ -1009,6 +1020,7 @@ fn spawn_menu_popover(commands: &mut Commands, font_res: Option<&FontResource>) .spawn(( option, ActionButton, + PopoverRow, Button, Tooltip::new(tooltip), Node { @@ -1139,9 +1151,20 @@ fn update_action_fade( /// `Last` (after `paint_action_buttons`) so a hover-state change in the /// same frame doesn't override the fade with an opaque idle / hover /// colour. +#[allow(clippy::type_complexity)] fn apply_action_fade( fade: Res, - mut buttons: Query<(&Children, &mut BackgroundColor), With>, + // Excludes `PopoverRow` so the auto-fade only applies to the + // top-level action bar buttons. Popover rows live inside an + // explicitly-opened dropdown panel and need to stay visible + // regardless of the bar's fade state — without the exclusion + // the rows fade to invisible while the popover container stays + // visible, leaving a solid background block with no readable + // content. + mut buttons: Query< + (&Children, &mut BackgroundColor), + (With, Without), + >, mut text_q: Query<&mut TextColor>, ) { for (children, mut bg) in &mut buttons {