feat(engine): hold-/ hotkey cheat sheet + unified binding table (Phase J)
Test / fmt (pull_request) Successful in 4s
Test / test (pull_request) Successful in 4m33s

Phase J audit findings: the visible focus ring the doc asked for
already exists (FocusOverlay singleton, 2px accent ring, breathing
pulse, reduce-motion aware — landed after the doc was written), and
post-Phase-C every modal already opens and dismisses keyboard-only.
The real gaps were two silently diverging static hotkey tables
(onboarding's slide vs Help's list — onboarding still said 'Mode
Launcher (then 1-5)') and no way to see the bindings mid-game.

- New crate::hotkeys module owns THE binding table (21 rows, verified
  against a grep inventory of every just_pressed(KeyCode::..) handler);
  rows carry an `essential` flag — the onboarding slide teaches that
  subset, the cheat sheet shows everything.
- New cheat_sheet_plugin: hold `/` for a right-anchored reference
  overlay of every binding; release hides it. Deliberately not a
  spawn_modal modal (momentary reference, closer to a tooltip), never
  spawns while a modal owns the screen (also keeps it out of the
  seed-entry field), inert on touch builds.
- Onboarding's stale local table deleted in favour of the shared one
  (copy updated: Home naming, hold-to-repeat undo, added H).

5 new tests (table integrity, essential-subset size, uniqueness,
show/hide driver, modal suppression). Workspace + clippy green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-13 18:57:43 -07:00
parent 4d9a07727a
commit 36605751cd
5 changed files with 389 additions and 82 deletions
+9 -8
View File
@@ -14,14 +14,14 @@ use crate::platform::{
};
use crate::{
AchievementPlugin, AnimationPlugin, AssetSourcesPlugin, AutoCompletePlugin,
CardAnimationPlugin, CardPlugin, ChallengePlugin, ContextualTipsPlugin, CursorPlugin,
DailyChallengePlugin, DiagnosticsHudPlugin, DifficultyPlugin, FeedbackAnimPlugin, FontPlugin,
GamePlugin, HelpPlugin, HomePlugin, HudPlugin, InputPlugin, OnboardingPlugin, PausePlugin,
PlayBySeedPlugin, ProfilePlugin, ProgressPlugin, RadialMenuPlugin, ReplayOverlayPlugin,
ReplayPlaybackPlugin, SafeAreaInsetsPlugin, SelectionPlugin, SettingsPlugin,
SolutionPlaybackPlugin, SplashPlugin, StatsPlugin, SyncProvider, TablePlugin, ThemePlugin,
ThemeRegistryPlugin, TimeAttackPlugin, TouchSelectionPlugin, UiFocusPlugin, UiModalPlugin,
UiTooltipPlugin, WeeklyGoalsPlugin, WhatsNewPlugin, WinSummaryPlugin,
CardAnimationPlugin, CardPlugin, ChallengePlugin, CheatSheetPlugin, ContextualTipsPlugin,
CursorPlugin, DailyChallengePlugin, DiagnosticsHudPlugin, DifficultyPlugin, FeedbackAnimPlugin,
FontPlugin, GamePlugin, HelpPlugin, HomePlugin, HudPlugin, InputPlugin, OnboardingPlugin,
PausePlugin, PlayBySeedPlugin, ProfilePlugin, ProgressPlugin, RadialMenuPlugin,
ReplayOverlayPlugin, ReplayPlaybackPlugin, SafeAreaInsetsPlugin, SelectionPlugin,
SettingsPlugin, SolutionPlaybackPlugin, SplashPlugin, StatsPlugin, SyncProvider, TablePlugin,
ThemePlugin, ThemeRegistryPlugin, TimeAttackPlugin, TouchSelectionPlugin, UiFocusPlugin,
UiModalPlugin, UiTooltipPlugin, WeeklyGoalsPlugin, WhatsNewPlugin, WinSummaryPlugin,
};
#[cfg(not(target_arch = "wasm32"))]
use crate::{
@@ -117,6 +117,7 @@ impl Plugin for CoreGamePlugin {
.add_plugins(OnboardingPlugin)
.add_plugins(WhatsNewPlugin)
.add_plugins(ContextualTipsPlugin)
.add_plugins(CheatSheetPlugin)
.add_plugins(WinSummaryPlugin)
.add_plugins(UiModalPlugin)
.add_plugins(UiFocusPlugin)