Add wrapping keyboard and gamepad focus rings
- Link every modal's enabled controls into a wrapping UiFocus ring and give each screen a default focus target. - Add gamepad A/B bindings for ui_accept/ui_cancel; include Start menu footer actions and Continue in its focus ring. - Skip hidden/disabled controls, close focus traps via per-modal cancel behavior, and return review to the menu on cancel. - Record the focus audit and add regression coverage.
This commit is contained in:
1 parent
9692f262f1
commit
8f65751975
17 files changed
+262
-76
No files matched your search
+21
-2
@@ -1,6 +1,6 @@
|
||||
# UI copy and button inventory
|
||||
|
||||
Status: dialogue and button-state passes complete; focus/layout audit in progress for 0.9.3.
|
||||
Status: dialogue, button-state and keyboard/gamepad focus passes complete; layout/end-to-end audit in progress for 0.9.3.
|
||||
|
||||
## Screen inventory
|
||||
|
||||
@@ -109,10 +109,29 @@ appeared when a custom dark button was disabled or focused by keyboard.
|
||||
| Radio | Send request, Send emergency, Cancel. Emergency hold uses press/release, so the action button stays enabled while holding. | All styled; disabling it during the hold would break confirmation. |
|
||||
| Toggles | CheckButton/OptionButton controls keep the engine theme. | Intentional: the shared style targets action buttons, not checkbox/radio affordances. |
|
||||
|
||||
## Keyboard and gamepad focus
|
||||
|
||||
`UiFocus` builds an explicit focus ring for each modal, skips hidden and
|
||||
disabled controls, and makes Up/Down, Tab/Shift+Tab and the D-pad/stick wrap.
|
||||
`GuardController._ensure_gamepad_bindings()` adds A to `ui_accept` and B to
|
||||
`ui_cancel`; the built-in directional UI actions already carry D-pad/stick
|
||||
events.
|
||||
|
||||
| Surface | Default focus | Cancellation / trap check |
|
||||
| --- | --- | --- |
|
||||
| Start menu | First visible target: Continue when present, otherwise the first venue. | A/Enter/Space activates the focused row; B/Esc quits; Continue, venue rows and footer actions share one wrapping ring. |
|
||||
| Pause | Resume. | B/Esc resumes; the four actions wrap. |
|
||||
| Settings | First slider. | B/Esc cancels; focus ring covers sliders, toggles, difficulty, rebinds, Apply and Cancel; sliders keep Left/Right for value adjustment. |
|
||||
| Help | Search field. | B/Esc closes; Search and Close share a ring. |
|
||||
| Shift review | Continue when available, otherwise the timeline. | B/Esc returns to the menu; all four actions are in the ring and hidden Continue is skipped. |
|
||||
| Timeline | First enabled action: Next when Previous is disabled, Close when empty. | B/Esc closes; Previous/Next leave the ring when disabled so focus cannot land on a dead button. |
|
||||
| Radio | Send action. | B/Esc cancels; form fields, action and Cancel are linked; A confirms the focused action. |
|
||||
| Tutorial | None; F1 is the documented skip shortcut. | Keyboard-only by design, no focus trap because the card is mouse-transparent and non-modal. |
|
||||
|
||||
## Remaining audit work
|
||||
|
||||
- Player-facing labels are now routed through `content/strings.en.json`; numeric
|
||||
values, empty-state clears and debug-only text remain in code by design.
|
||||
- Verify focus/hover/pressed/disabled states with keyboard, gamepad and mouse.
|
||||
- Focus/hover/pressed/disabled states and keyboard/gamepad rings are recorded above.
|
||||
- Test long strings and 1.75x HUD font scale.
|
||||
- Capture every dialog/button state and run `screen_designs.py compare` plus the pinned judge.
|
||||
Reference in new issue
Block a user