Standardize button labels and document UI states
Full build / Import + headless tests (push) Successful in 38s
Full build / Full desktop build + optional release (push) Skipped

Finish the button-label audit with a surface-by-surface table, clarify Quit
game vs Quit to menu, rename Apply to Apply settings, and use string-table
keys for the new labels. Extend the smoke checklist with UI copy/button checks.
Headless 250/250, docs check OK.
This commit is contained in:
zwitschi committed 2026-11-02 11:12:29 +01:00
1 parent 7c48183410
commit 844e39246a
7 files changed
+45 -5

No files matched your search

+3 -2
View File
@@ -57,8 +57,9 @@ screen-design judge before any model/texture changes. No gameplay rules change.
- [x] Record the canonical terms for admit/refuse, warning/blocking, - [x] Record the canonical terms for admit/refuse, warning/blocking,
assistance/emergency, body camera, shift review and campaign; the current assistance/emergency, body camera, shift review and campaign; the current
inspection/wand/radio/review labels use them (see `docs/ui-copy.md`). inspection/wand/radio/review labels use them (see `docs/ui-copy.md`).
- [ ] Audit all button labels for verb-first wording, capitalization, ordering, - [x] Audit all button labels for verb-first wording, capitalization, ordering,
destructive-action confirmation and consistent confirm/cancel placement. destructive-action confirmation and consistent confirm/cancel placement;
recorded in `docs/ui-copy.md` and fixed Quit/Apply wording.
- [ ] List every hardcoded player-facing string and route it through - [ ] List every hardcoded player-facing string and route it through
`content/strings.en.json`; add placeholder validation for new keys. `content/strings.en.json`; add placeholder validation for new keys.
- [ ] Review NPC/door-staff/radio/tutorial/help/review/campaign dialogue for - [ ] Review NPC/door-staff/radio/tutorial/help/review/campaign dialogue for
+2
View File
@@ -108,5 +108,7 @@
"ui.radio_cancelled": "Call cancelled — hold the button.", "ui.radio_cancelled": "Call cancelled — hold the button.",
"ui.radio_holding": "Holding… %.0f%%", "ui.radio_holding": "Holding… %.0f%%",
"ui.review_return_menu": "Return to menu", "ui.review_return_menu": "Return to menu",
"ui.quit_game": "Quit game",
"ui.apply_settings": "Apply settings",
"tutorial.skipped": "Tutorial skipped." "tutorial.skipped": "Tutorial skipped."
} }
+2
View File
@@ -40,3 +40,5 @@
38. Master/SFX/ambience volume settings clamp at 0/1 and persist; Reduce motion disables head bob; the captions toggle persists. 38. Master/SFX/ambience volume settings clamp at 0/1 and persist; Reduce motion disables head bob; the captions toggle persists.
39. The 24-NPC budget smoke stays inside its frame budget; coats/dresses do not show obvious leg clipping in a normal walk. 39. The 24-NPC budget smoke stays inside its frame budget; coats/dresses do not show obvious leg clipping in a normal walk.
40. Help remains readable with the largest HUD font scale, and CI/local verification use the same Godot 4.7.2 baseline. 40. Help remains readable with the largest HUD font scale, and CI/local verification use the same Godot 4.7.2 baseline.
41. UI copy: inspection/wand use "A = admit · D = refuse entry", review returns with "Return to menu", and application exit reads "Quit game".
42. Button states remain readable on hover/focus/pressed; settings Apply/Cancel and radio normal-send/emergency-hold behave as labelled.
+33
View File
@@ -31,12 +31,45 @@ Status: audit in progress for the 0.9.2 UI polish patch.
- **Return to menu** — leave the review to the venue menu (it does not start a new shift by itself). - **Return to menu** — leave the review to the venue menu (it does not start a new shift by itself).
- **Send request** — non-emergency assistance; **Send emergency** — emergency call. - **Send request** — non-emergency assistance; **Send emergency** — emergency call.
## Button labels and states
| Surface | Label | Behavior | State audit |
| --- | --- | --- | --- |
| Start menu | Continue shift — <venue> | Resume/advance campaign | Hidden when complete; venue-specific |
| Start menu | Venue rows | Start free-play/campaign venue | Hover/focus/pressed styled |
| Start menu | Help | Open Help overlay | Standard button |
| Start menu | Settings | Open Settings | Standard button |
| Start menu | Quit game | Exit application | Destructive; label clarifies scope |
| Tutorial | F1 skip tutorial | Skip lesson | Keyboard only, non-blocking |
| Action wheel | Stop/Look/Point/No/Ask/Inspect/Wand/Warn/Block/Reason/Recognize/Radio | Choose verb | Hover/selection highlight |
| Inspection | A = admit · D = refuse entry | Access decision | Keyboard hints, policy text |
| Wand | A = admit · D = refuse entry | Screening decision | Keyboard hints, item/alert text |
| Radio | Send request | Submit assistance | Normal click |
| Radio | Send emergency | Submit emergency | Hold-to-confirm; Cancel aborts |
| Radio | Cancel | Close form | Standard button |
| Pause | Resume | Resume shift | Default focus |
| Pause | Restart shift | Restart current shift | Standard button |
| Pause | Settings | Open Settings | Standard button |
| Pause | Quit to menu | Return to venue menu | Standard button |
| Settings | Apply settings | Persist settings | Standard button |
| Settings | Cancel | Discard edits | Standard button |
| Settings | Replay tutorial | Clear tutorial flags and restart Hollywood | Standard button |
| Settings | Reset campaign | Confirmed campaign reset | Confirmation dialog |
| Help | Close | Close overlay | Standard button |
| Review | Continue campaign | Start next venue | Hidden when campaign complete |
| Review | Body camera timeline | Open event timeline | Standard button |
| Review | Return to menu | Return to venue menu | Standard button |
| Review | Quit game | Exit application | Standard button |
| Timeline | Previous / Next / Close | Step/close evidence | Standard buttons |
## Button/label issues found ## Button/label issues found
- HUD inspection and wand used “allow/deny” versus “admit/refuse”; both now use **A = admit · D = refuse entry**. - HUD inspection and wand used “allow/deny” versus “admit/refuse”; both now use **A = admit · D = refuse entry**.
- Shift review’s old “Run another shift” actually returned to the menu; renamed **Return to menu**. - Shift review’s old “Run another shift” actually returned to the menu; renamed **Return to menu**.
- Radio emergency action used all-caps while assistance used sentence case; both are now sentence case, with the warning in the panel title/hold hint. - Radio emergency action used all-caps while assistance used sentence case; both are now sentence case, with the warning in the panel title/hold hint.
- Normal radio send was previously wired only to the emergency hold handlers; fixed in 0.8.1 and covered by `test_radio_panel.gd`. - Normal radio send was previously wired only to the emergency hold handlers; fixed in 0.8.1 and covered by `test_radio_panel.gd`.
- “Quit” was ambiguous between menu and application exit; both application-exit buttons now read **Quit game**.
- Settings “Apply” was made verb+object as **Apply settings**.
## Remaining audit work ## Remaining audit work
+2 -1
View File
@@ -8,6 +8,7 @@ extends CanvasLayer
const InputBindings := preload("res://src/core/input_bindings.gd") const InputBindings := preload("res://src/core/input_bindings.gd")
const UiArt := preload("res://src/game/ui/art.gd") const UiArt := preload("res://src/game/ui/art.gd")
const Strings := preload("res://src/core/strings.gd")
signal applied(settings: Dictionary) signal applied(settings: Dictionary)
signal replay_tutorial_requested() signal replay_tutorial_requested()
@@ -169,7 +170,7 @@ func _build() -> void:
var save_button := Button.new() var save_button := Button.new()
save_button.name = "ApplyButton" save_button.name = "ApplyButton"
save_button.text = "Apply" save_button.text = Strings.lookup("ui.apply_settings")
save_button.pressed.connect(_on_apply) save_button.pressed.connect(_on_apply)
row.add_child(save_button) row.add_child(save_button)
+1 -1
View File
@@ -74,7 +74,7 @@ func _init() -> void:
center.add_child(restart) center.add_child(restart)
var quit_btn := Button.new() var quit_btn := Button.new()
quit_btn.text = "Quit" quit_btn.text = Strings.lookup("ui.quit_game")
quit_btn.pressed.connect(func(): get_tree().quit()) quit_btn.pressed.connect(func(): get_tree().quit())
quit_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER quit_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
_style_review_button(timeline) _style_review_button(timeline)
+2 -1
View File
@@ -11,6 +11,7 @@ signal settings_requested()
signal quit_requested() signal quit_requested()
const UiArt := preload("res://src/game/ui/art.gd") const UiArt := preload("res://src/game/ui/art.gd")
const Strings := preload("res://src/core/strings.gd")
const VENUES := [ const VENUES := [
{"id": "hollywood_building", "label": "Hollywood Boulevard", "blurb": "Building entrance, tourists and late-night trouble."}, {"id": "hollywood_building", "label": "Hollywood Boulevard", "blurb": "Building entrance, tourists and late-night trouble."},
@@ -142,7 +143,7 @@ func _build() -> void:
var quit_button := Button.new() var quit_button := Button.new()
quit_button.name = "QuitButton" quit_button.name = "QuitButton"
quit_button.text = "Quit" quit_button.text = Strings.lookup("ui.quit_game")
quit_button.pressed.connect(func(): quit_requested.emit()) quit_button.pressed.connect(func(): quit_requested.emit())
row.add_child(quit_button) row.add_child(quit_button)