feat(engine): opt Profile / Leaderboard / Home into scrim-click dismiss

Follow-up to a54201e. The previous commit added ScrimDismissible to
Stats, Achievements, and Help; this one extends the same one-line
opt-in to the remaining three read-only modals so the click-outside-
to-close gesture is consistent across every informational surface.

Each modal now has the same shape: capture the scrim from
spawn_modal, attach ScrimDismissible after the build closure
returns. Three lines per file plus the import; no behaviour change
to the modal content itself.

Settings, Onboarding, Pause, Forfeit confirm, ConfirmNewGame, and
the win/game-over modals continue to opt OUT — all carry unsaved
or destructive state where an accidental scrim click would lose
work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-06 00:47:02 +00:00
parent a54201e97b
commit cbf2483028
3 changed files with 12 additions and 3 deletions
+4 -1
View File
@@ -26,6 +26,7 @@ use crate::progress_plugin::ProgressResource;
use crate::ui_focus::{Disabled, FocusGroup, Focusable};
use crate::ui_modal::{
spawn_modal, spawn_modal_actions, spawn_modal_button, spawn_modal_header, ButtonVariant,
ScrimDismissible,
};
use crate::ui_theme::{
ACCENT_PRIMARY, BG_ELEVATED_HI, BORDER_STRONG, BORDER_SUBTLE, RADIUS_MD, STATE_INFO,
@@ -359,7 +360,7 @@ fn handle_home_digit_keys(
/// Spawns the Home modal with five mode cards plus a Cancel button.
fn spawn_home_screen(commands: &mut Commands, level: u32, font_res: Option<&FontResource>) {
spawn_modal(commands, HomeScreen, Z_MODAL_PANEL, |card| {
let scrim = spawn_modal(commands, HomeScreen, Z_MODAL_PANEL, |card| {
spawn_modal_header(card, "Choose a Mode", font_res);
for mode in [
@@ -383,6 +384,8 @@ fn spawn_home_screen(commands: &mut Commands, level: u32, font_res: Option<&Font
);
});
});
// Home is read-only — opt into click-outside-to-dismiss.
commands.entity(scrim).insert(ScrimDismissible);
}
/// Tab-walk order for each mode card, matching the visual top-to-bottom
+4 -1
View File
@@ -21,6 +21,7 @@ use crate::settings_plugin::SettingsResource;
use crate::sync_plugin::SyncProviderResource;
use crate::ui_modal::{
spawn_modal, spawn_modal_actions, spawn_modal_button, spawn_modal_header, ButtonVariant,
ScrimDismissible,
};
use crate::ui_theme::{
ACCENT_PRIMARY, BORDER_SUBTLE, STATE_INFO, TEXT_PRIMARY, TEXT_SECONDARY, TYPE_BODY,
@@ -392,7 +393,7 @@ fn spawn_leaderboard_screen(
remote_available: bool,
font_res: Option<&FontResource>,
) {
spawn_modal(commands, LeaderboardScreen, Z_MODAL_PANEL, |card| {
let scrim = spawn_modal(commands, LeaderboardScreen, Z_MODAL_PANEL, |card| {
spawn_modal_header(card, "Leaderboard", font_res);
// Subhead — what the screen does + what the buttons control.
@@ -566,6 +567,8 @@ fn spawn_leaderboard_screen(
);
});
});
// Leaderboard is read-only — opt into click-outside-to-dismiss.
commands.entity(scrim).insert(ScrimDismissible);
}
fn header_cell(parent: &mut ChildSpawnerCommands, text: &str, width: f32, font: &TextFont) {
+4 -1
View File
@@ -20,6 +20,7 @@ use crate::settings_plugin::SettingsResource;
use crate::stats_plugin::{format_fastest_win, format_win_rate, StatsResource};
use crate::ui_modal::{
spawn_modal, spawn_modal_actions, spawn_modal_button, spawn_modal_header, ButtonVariant,
ScrimDismissible,
};
use crate::ui_theme::{
ACCENT_PRIMARY, BG_ELEVATED, BORDER_STRONG, SPACE_1, STATE_INFO, STATE_SUCCESS, TEXT_PRIMARY,
@@ -184,7 +185,7 @@ fn spawn_profile_screen(
..default()
};
spawn_modal(commands, ProfileScreen, Z_MODAL_PANEL, |card| {
let scrim = spawn_modal(commands, ProfileScreen, Z_MODAL_PANEL, |card| {
spawn_modal_header(card, "Profile", font_res);
// Scrollable body — the Profile panel renders sync info,
@@ -395,6 +396,8 @@ fn spawn_profile_screen(
);
});
});
// Profile is read-only — opt into click-outside-to-dismiss.
commands.entity(scrim).insert(ScrimDismissible);
}
/// Spawn a fixed-height vertical spacer node.