mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 01:37:05 +00:00
Release 1.1.0 — one config file, and a process weight you choose
`project.yaml` at the repo root is now the single source of truth for a project's configuration, replacing `production/stage.txt`, `production/review-mode.txt` and `.claude/docs/technical-preferences.md` (all three still read as a fallback; nothing is force-deleted). **`modes.rigor` — one question instead of six.** `minimal`, `standard` or `full` fronts six knobs: `modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`, `modes.review_mode` and `team.size`. It defaults to `minimal`, which is a change from 1.0's behaviour: the heavier tier was measured costing several times more to reach working code without producing a better result, and returning nothing when a fresh developer inherited the project. Pin `modes.rigor: standard` to keep 1.0's process level. Also in this release: - `/settings` to view or change any setting, and `project.local.yaml` for per-developer preferences that should not be committed. - `system_overrides` to hold one system to a higher standard than the rest of the project, and `testing.strict` to set per test type whether missing evidence blocks a story or warns. - A story that changes anything the player sees is not closed until the game has been launched, observed, and a screenshot retained in `production/qa/evidence/`. A parse check is not a run. This holds at every rigor level, including `minimal`, where automated tests are waived but the look is not. - The code root is engine-specific and enforced as such: Godot `src/`, Unity `Assets/`, Unreal `Source/<Module>/`. Two of the three will not build a project laid out any other way. - Migration tooling for existing projects: `.claude/scripts/migrate-v1-config.sh` converts a 1.0 layout, non-destructively by default, with a report to review before `--finalize` deletes anything. - Ask-before-write holds regardless of personal automation settings. Upgrading from 1.0 or earlier: see UPGRADING.md. Full list of changes: CHANGELOG.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016xvzG3i7pWQg4LjyDwWMXd
This commit is contained in:
co-authored by
Claude Opus 5
parent
984023ddac
commit
d05699707f
@@ -0,0 +1,210 @@
|
||||
> Authoring guidance for accessibility-requirements.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
# Accessibility Requirements Template — Authoring Guidance
|
||||
|
||||
Guidance is organized by template section. When authoring a section of a
|
||||
project's accessibility requirements document, read only that section's
|
||||
guidance below. The feature tables themselves (Visual / Motor / Cognitive /
|
||||
Auditory), the platform API table, the test plan, and the external resources
|
||||
remain in the template — they are the requirement catalog, not guidance.
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Tier Definition
|
||||
|
||||
> **Why define tiers**: Accessibility is not binary. Defining four tiers gives
|
||||
> the team a shared vocabulary, forces an explicit commitment at the start of
|
||||
> production, and prevents scope creep in both directions ("we'll add it later"
|
||||
> and "we have to support everything"). The tiers below are this project's
|
||||
> definitions — the industry uses similar but not identical language. Commit to
|
||||
> a tier with specific feature targets, not just the tier name.
|
||||
|
||||
**Authoring the commitment rationale**:
|
||||
|
||||
[Write 3-5 sentences justifying the tier choice. Do not simply
|
||||
state the tier — explain the reasoning. Consider: What is the game's genre and
|
||||
how does it map to common accessibility barriers (e.g., fast-twitch games have
|
||||
motor barriers; reading-heavy games have visual barriers)? Who is the target
|
||||
player and what does the research say about disability prevalence in that group?
|
||||
What are the platform requirements (Xbox requires XAG compliance for ID@Xbox)?
|
||||
What is the team's capacity? What would dropping one tier cost the player base,
|
||||
in concrete terms?
|
||||
|
||||
Example: "This is a narrative RPG with turn-based combat targeted at players
|
||||
25-45. The turn-based structure eliminates the most severe motor barriers common
|
||||
in action games, but the reading-heavy design creates significant visual and
|
||||
cognitive barriers. Standard tier addresses all of these. Exemplary tier is not
|
||||
achievable without a dedicated accessibility engineer. Xbox ID@Xbox program
|
||||
requires XAG compliance for Game Pass consideration, which Standard meets.
|
||||
Dropping to Basic would exclude players who rely on colorblind modes or input
|
||||
remapping, estimated at 8-12% of the target audience based on AbleGamers data."]
|
||||
|
||||
**Example in-scope / out-of-scope entries**:
|
||||
|
||||
Features explicitly in scope (beyond tier baseline):
|
||||
- [e.g., "Full subtitle customization — elevated from Comprehensive because our
|
||||
game is dialogue-heavy and subtitles are a primary channel"]
|
||||
- [e.g., "One-hand mode for controller — we have hold inputs critical to combat"]
|
||||
|
||||
Features explicitly out of scope:
|
||||
- [e.g., "Screen reader for in-game world (not menus) — requires engine work
|
||||
beyond current capacity. Documented in Known Intentional Limitations."]
|
||||
|
||||
---
|
||||
|
||||
## Visual Accessibility
|
||||
|
||||
> **Why this section comes first**: Visual impairments affect the largest
|
||||
> proportion of players who use accessibility features. Color vision deficiency
|
||||
> alone affects approximately 8% of men and 0.5% of women. Text legibility at
|
||||
> TV viewing distance is frequently the single largest accessibility failure
|
||||
> in shipped games. Document every visual feature before implementation begins,
|
||||
> because retrofitting minimum text sizes or color decisions after assets are
|
||||
> locked is expensive.
|
||||
|
||||
**Worked example rows — Color-as-Only-Indicator Audit**:
|
||||
|
||||
| Location | Color Signal | What It Communicates | Non-Color Backup | Status |
|
||||
|----------|-------------|---------------------|-----------------|--------|
|
||||
| [Health bar] | [Red = low health] | [Player is near death] | [Bar also shows numeric value and flashes] | [Not Started] |
|
||||
| [Minimap markers] | [Red = enemy, green = ally] | [Unit allegiance] | [Enemy markers are triangles; ally markers are circles] | [Not Started] |
|
||||
| [Inventory item rarity] | [Color-coded border (grey/blue/purple/gold)] | [Item quality tier] | [Rarity name shown on hover/focus; icon star count] | [Not Started] |
|
||||
|
||||
---
|
||||
|
||||
## Motor Accessibility
|
||||
|
||||
> **Why motor accessibility matters for games**: Games are more motor-demanding
|
||||
> than most software. A web form requires precise clicks; a game may require
|
||||
> rapid simultaneous button combinations held for specific durations. Motor
|
||||
> impairments span a wide range — from tremor (affecting precision) to
|
||||
> hemiplegia (one functional hand) to RSI (affecting hold duration). The AbleGamers
|
||||
> Able Assistance program estimates 35 million gamers in the US have a disability
|
||||
> affecting their ability to play. Many of the features below cost very little
|
||||
> to implement if planned from the start, and are extremely expensive to add post-launch.
|
||||
|
||||
---
|
||||
|
||||
## Cognitive Accessibility
|
||||
|
||||
> **Why cognitive accessibility is often under-specced**: Cognitive accessibility
|
||||
> affects players with ADHD, dyslexia, autism spectrum conditions, acquired brain
|
||||
> injuries, and anxiety disorders — a larger combined population than many studios
|
||||
> realize. It also benefits all players in high-stress moments. The most common
|
||||
> failures are: no pause anywhere, tutorial information that can only be seen once,
|
||||
> and systems that require tracking too many simultaneous states. Games like
|
||||
> Hades and Celeste have demonstrated that cognitive assist options (god mode,
|
||||
> persistent reminders, extended text display) do not harm the experience for
|
||||
> players who don't use them.
|
||||
|
||||
---
|
||||
|
||||
## Auditory Accessibility
|
||||
|
||||
> **Why auditory accessibility matters even for players without hearing loss**:
|
||||
> 7% of players are deaf or hard of hearing. Additionally, a large portion of
|
||||
> players regularly play in environments where audio is reduced or absent (commute,
|
||||
> shared household, infant sleeping). Any gameplay-critical information delivered
|
||||
> only through audio is a design failure even before accessibility is considered.
|
||||
> The guiding principle: every sound that changes what the player should DO next
|
||||
> must have a visual equivalent.
|
||||
|
||||
**Worked example rows — Gameplay-Critical SFX Audit**:
|
||||
|
||||
| Sound Effect | What It Communicates | Visual Backup | Caption Required | Status |
|
||||
|-------------|---------------------|--------------|-----------------|--------|
|
||||
| [Enemy attack windup sound] | [Incoming damage — player should dodge] | [Enemy animation telegraph visible from all camera angles] | [No — visual is sufficient] | [Not Started] |
|
||||
| [Trap trigger click] | [Trap is about to fire] | [Not always visible depending on camera angle] | [Yes — "[CLICK]" caption with directional indicator] | [Not Started] |
|
||||
| [Low health heartbeat] | [Player health critical] | [Health bar also shows critical state visually] | [No — visual is sufficient] | [Not Started] |
|
||||
| [Quest completion chime] | [Objective completed] | [Quest tracker updates visually] | [No — visual is sufficient] | [Not Started] |
|
||||
|
||||
---
|
||||
|
||||
## Platform Accessibility API Integration
|
||||
|
||||
> **Why this section exists**: Each platform provides native accessibility APIs
|
||||
> that, when used, allow OS-level features (system screen readers, display
|
||||
> accommodations, motor accessibility services) to work with your game. Ignoring
|
||||
> these APIs does not break the game, but it means players who rely on OS-level
|
||||
> accessibility tools get no benefit from them inside your game. Xbox in particular
|
||||
> requires XAG compliance for certification. Verify platform requirements before
|
||||
> committing to a tier — platform requirements set a floor, not a ceiling.
|
||||
|
||||
---
|
||||
|
||||
## Per-Feature Accessibility Matrix
|
||||
|
||||
> **Why this matrix exists**: Accessibility is not a list of settings — it is a
|
||||
> property of every game system. This matrix creates the "accessibility impact"
|
||||
> view of the game: which systems have which barriers, and whether those barriers
|
||||
> are addressed. When a new system is added to systems-index.md, a row must be
|
||||
> added here. If a system has an unaddressed accessibility concern, it cannot be
|
||||
> marked Approved in the systems index.
|
||||
|
||||
**Worked example rows**:
|
||||
|
||||
| System | Visual Concerns | Motor Concerns | Cognitive Concerns | Auditory Concerns | Addressed | Notes |
|
||||
|--------|----------------|---------------|-------------------|------------------|-----------|-------|
|
||||
| [Combat System] | [Enemy health bars are color-coded; attack animations may cause motion sickness] | [Rapid input required for combos; hold inputs for guard] | [Track enemy patterns + cooldowns + player resources simultaneously] | [Audio cues for off-screen attacks; critical damage warning sounds] | [Partial] | [Colorblind palette applied; hold-to-block toggle needed] |
|
||||
| [Inventory / Equipment] | [Item rarity conveyed by border color] | [No motor concerns — turn-based] | [Item stats comparison requires reading multiple values] | [None — no critical audio in this system] | [Partial] | [Non-color rarity indicators in progress] |
|
||||
| [Dialogue System] | [Subtitle display depends on contrast settings] | [No motor concerns] | [Long dialogue trees with time pressure on dialogue choices] | [All dialogue must be subtitled] | [Not Started] | [Timed dialogue choices must support extended timer option] |
|
||||
| [Navigation / World Map] | [Map marker colors] | [No motor concerns] | [Quest objective clarity; waypoint visibility] | [Audio pings for objectives have no visual equivalent] | [Not Started] | |
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Test Plan
|
||||
|
||||
> **Why testing accessibility separately from QA**: Standard QA tests whether
|
||||
> features work. Accessibility testing tests whether features work for players
|
||||
> who use them. These are different tests. A subtitle system can pass QA (it
|
||||
> displays text) and fail accessibility testing (the text is unreadable at TV
|
||||
> distance by a player with low vision). Plan for three test types: automated
|
||||
> (contrast ratios, text sizes), manual internal (team members simulating
|
||||
> impairments using accessibility simulators), and user testing (players who
|
||||
> actually use these features).
|
||||
|
||||
---
|
||||
|
||||
## Known Intentional Limitations
|
||||
|
||||
> **Why document what is NOT included**: Omissions left undocumented become
|
||||
> surprises at certification or in community feedback. Documenting a limitation
|
||||
> with a rationale demonstrates that it was a deliberate choice, not an oversight.
|
||||
> It also identifies which players are not served and what the mitigation is.
|
||||
> Every entry here is a risk — assess it honestly.
|
||||
|
||||
**Worked example rows**:
|
||||
|
||||
| Feature | Tier Required | Why Not Included | Risk / Impact | Mitigation |
|
||||
|---------|--------------|-----------------|--------------|------------|
|
||||
| [Screen reader support for in-game world (NPCs, objects, environmental text)] | Exemplary | Engine (Godot 4.6) AccessKit integration covers menus only; extending to the game world requires a custom spatial audio description system beyond current scope | Affects blind and low-vision players who can navigate menus but cannot independently explore the game world | Ensure all critical world information is duplicated in accessible menu systems (quest log, map); evaluate for post-launch DLC |
|
||||
| [Full subtitle customization (font/color/background)] | Comprehensive | Scope reduction — targeting Standard tier. Custom font rendering in Godot requires additional asset pipeline work | Affects deaf and hard-of-hearing players with specific legibility needs; particularly affects players with dyslexia who use custom fonts | Provide two preset subtitle styles (default and high-readability) as a partial mitigation; log for post-launch update |
|
||||
| [Tactile/haptic alternatives for all audio cues] | Exemplary | Platform rumble API integration for non-Xbox platforms is out of scope for v1.0 | Affects deaf players relying on haptic feedback; PC players with non-Xbox controllers get no haptic response | Xbox controller haptic integration is in scope; evaluate PlayStation DualSense haptic API for a post-launch patch |
|
||||
|
||||
---
|
||||
|
||||
## Audit History
|
||||
|
||||
> **Why track audit history**: Accessibility is not certified once and done.
|
||||
> Platform requirements change. New features may introduce new barriers. Legal
|
||||
> standards evolve. An audit history demonstrates due diligence and helps identify
|
||||
> regressions between audits.
|
||||
|
||||
**Worked example rows**:
|
||||
|
||||
| Date | Auditor | Type | Scope | Findings Summary | Status |
|
||||
|------|---------|------|-------|-----------------|--------|
|
||||
| [Date] | [Internal — ux-designer] | Internal review | [Pre-submission checklist against committed tier] | [e.g., "12 items verified, 3 open issues: subtitle contrast below target in 2 scenes, color-only indicator on minimap not resolved"] | [In Progress] |
|
||||
| [Date] | [External — AbleGamers Player Panel] | User testing | [Motor accessibility — one-hand mode and timing adjustments] | [e.g., "Toggle modes functional. Timed QTE window at 3x still failed for one participant — recommend 5x option."] | [Findings addressed] |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
**Worked example questions**:
|
||||
|
||||
| Question | Owner | Deadline | Resolution |
|
||||
|----------|-------|----------|-----------|
|
||||
| [Does Godot 4.6 AccessKit support dynamic accessibility node updates for HUD elements, or only static menus?] | [ux-designer] | [Before Technical Setup gate] | [Unresolved — check engine-reference/godot/ docs] |
|
||||
| [What is the Xbox ID@Xbox minimum XAG compliance requirement for our release window?] | [producer] | [Before Pre-Production gate] | [Unresolved] |
|
||||
| [Will the dialogue system support timed choice extensions without a full architecture change?] | [lead-programmer] | [During Technical Design] | [Unresolved] |
|
||||
+380
@@ -0,0 +1,380 @@
|
||||
> Authoring guidance for hud-design.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
# HUD Design Template — Authoring Guidance
|
||||
|
||||
Guidance is organized by template section number. When authoring a section of a
|
||||
project's HUD design document, read only that section's guidance below.
|
||||
|
||||
---
|
||||
|
||||
## Section 1 — HUD Philosophy
|
||||
|
||||
> **Why this section exists**: The HUD design philosophy is not decoration — it is a
|
||||
> design constraint that every subsequent decision is measured against. Without a
|
||||
> philosophy, individual elements get added on request ("the quest tracker wants a
|
||||
> bigger icon") without any principled way to push back. With a philosophy, there is
|
||||
> a shared, explicit standard. More importantly, the philosophy prevents the HUD from
|
||||
> slowly growing to cover the game world while each individual addition seemed
|
||||
> reasonable in isolation. Write this before specifying any elements.
|
||||
|
||||
**Authoring the philosophy statement**:
|
||||
|
||||
[One paragraph. This is a design statement, not a description of features. Consider
|
||||
the game's genre, pacing, and player fantasy. A stealth game's HUD philosophy might
|
||||
be: "The world is the interface. If the player has to look away from the environment
|
||||
to survive, the HUD has failed." A tactics game might say: "Complete situational
|
||||
awareness is the game. The HUD is not an overlay — it is the battlefield."
|
||||
|
||||
Reference comparable games if helpful, but describe your specific stance:
|
||||
Example — diegetic-first action RPG: "We treat screen information as a concession,
|
||||
not a feature. Every HUD element must earn its pixel space by answering the question:
|
||||
would the player make demonstrably worse decisions without this information visible?
|
||||
If the answer is 'they'd adapt,' we put it in the environment instead."]
|
||||
|
||||
**Authoring the visibility principle**:
|
||||
|
||||
[State the default resolution for ambiguous cases. Options:
|
||||
- Default to HIDE: information is available on demand (e.g., Dark Souls — no quest tracker, no minimap, stats are in a menu)
|
||||
- Default to SHOW: players prefer to be informed; cluttered is better than uncertain
|
||||
- Default to CONTEXTUAL: information appears when it becomes relevant and fades when it does not
|
||||
Most games benefit from contextual defaults. State your game's default clearly so every element decision is consistent.]
|
||||
|
||||
**Authoring the Rule of Necessity**:
|
||||
|
||||
[Complete this sentence: "A HUD element earns its place when ______________."
|
||||
|
||||
Example: "...the player would have to stop playing to find the same information
|
||||
elsewhere, or would make meaningfully worse decisions without it."
|
||||
|
||||
Example: "...removing it in playtesting causes measurable frustration or confusion
|
||||
in more than 25% of testers within the first hour of play."
|
||||
|
||||
This rule is the veto power over feature requests to add HUD elements. Document it
|
||||
so it can be cited in design reviews.]
|
||||
|
||||
---
|
||||
|
||||
## Section 2 — Information Architecture
|
||||
|
||||
> **Why this section exists**: Before specifying any HUD element's visual design,
|
||||
> position, or behavior, you must answer a more fundamental question: should this
|
||||
> information be on the HUD at all? This section is a forcing function — it requires
|
||||
> you to categorize EVERY piece of information the game world generates and make an
|
||||
> explicit, intentional decision about how each is presented. "We'll figure that out
|
||||
> later" is how games end up with 18 elements competing for the player's peripheral
|
||||
> vision. This table is the master inventory of game information, not just HUD information.
|
||||
|
||||
**Worked example table** (typical information types and categorization reasoning):
|
||||
|
||||
| Information Type | Always Show | Contextual (show when relevant) | On Demand (menu/button) | Hidden (environmental / diegetic) | Reasoning |
|
||||
|-----------------|-------------|--------------------------------|------------------------|----------------------------------|-----------|
|
||||
| [Health / Vitality] | [X if action game — player needs constant awareness] | [X if exploration game — show only when injured] | [ ] | [ ] | [Example: always visible because health decisions (retreat, heal) must be instant in combat] |
|
||||
| [Primary resource (mana / stamina / ammo)] | [ ] | [X — show when resource is being consumed or is critically low] | [ ] | [ ] | [Example: contextual because stable resource levels are not decision-relevant] |
|
||||
| [Secondary resource (currency / materials)] | [ ] | [ ] | [X — check in inventory] | [ ] | [Example: on-demand because resource totals don't affect immediate gameplay decisions] |
|
||||
| [Minimap / Compass] | [X] | [ ] | [ ] | [ ] | [Example: always visible because navigation decisions are constant during exploration] |
|
||||
| [Quest objective] | [ ] | [X — show when objective changes or player is near it] | [ ] | [ ] | [Example: contextual — player knows their objective; only remind at key moments] |
|
||||
| [Enemy health bar] | [ ] | [X — show only during combat encounters] | [ ] | [ ] | [Example: contextual because enemy health is irrelevant outside combat] |
|
||||
| [Status effects (buffs/debuffs)] | [ ] | [X — show when active] | [ ] | [ ] | [Example: contextual because status effects only affect decisions when present] |
|
||||
| [Dialogue subtitles] | [X when dialogue is playing] | [ ] | [ ] | [ ] | [Example: always show while dialogue is active — accessibility requirement] |
|
||||
| [Combo / streak counter] | [ ] | [X — show while combo is active, hide on reset] | [ ] | [ ] | [Example: contextual because it communicates active performance, not baseline state] |
|
||||
| [Timer] | [ ] | [X — show only in timed sequences] | [ ] | [ ] | [Example: contextual because timers only exist in specific encounter types] |
|
||||
| [Tutorial prompts] | [ ] | [X — show for first-time situations only] | [ ] | [ ] | [Example: contextual and one-time; never repeat to experienced players] |
|
||||
| [Score / points] | [ ] | [X — show in score-relevant modes only] | [ ] | [ ] | [Example: contextual by game mode; hidden in modes where score is irrelevant] |
|
||||
| [XP / level progress] | [ ] | [ ] | [X — available via character screen] | [ ] | [Example: on-demand because progression does not affect in-moment gameplay decisions] |
|
||||
| [Waypoint / objective marker] | [ ] | [X — show when player is navigating to objective] | [ ] | [ ] | [Example: contextual — suppress during cutscenes, cinematic moments, and free exploration] |
|
||||
|
||||
---
|
||||
|
||||
## Section 3 — Layout Zones
|
||||
|
||||
> **Why this section exists**: The game world is the primary content — the HUD is a
|
||||
> frame around it. Before placing any element, divide the screen into named zones
|
||||
> with explicit positions and safe zone margins. This section prevents two failure
|
||||
> modes: (1) elements placed ad-hoc until the screen is cluttered, and (2) elements
|
||||
> that overlap platform-required safe zones and get rejected in certification.
|
||||
> Every element in Section 4 must be assigned to a zone defined here.
|
||||
|
||||
**Worked example — zone specification table**:
|
||||
|
||||
| Zone Name | Screen Position | Safe Zone Compliant | Primary Elements | Max Simultaneous Elements | Notes |
|
||||
|-----------|----------------|---------------------|-----------------|--------------------------|-------|
|
||||
| [Top Left] | [Top-left corner, within safe margin] | [Yes — 10% from top, 10% from left] | [Health bar, stamina bar, shield bar] | [3] | [Vital status — player's own resources. Priority zone for player state.] |
|
||||
| [Top Center] | [Top edge, centered horizontally] | [Yes — 10% from top] | [Quest objective, area name (on enter)] | [1 — only one message at a time] | [Use for narrative context, not mechanical information. Keep text minimal.] |
|
||||
| [Top Right] | [Top-right corner, within safe margin] | [Yes — 10% from top, 10% from right] | [Ammo count, ability cooldowns] | [2] | [Weapon/ability state. Most relevant during active combat.] |
|
||||
| [Center] | [Screen center ±15%] | [N/A — not a margin zone] | [Crosshair, interaction prompt, hit marker] | [1 active at a time] | [CRITICAL: Nothing persistent here. Only momentary indicators.] |
|
||||
| [Bottom Left] | [Bottom-left corner, within safe margin] | [Yes — 10% from bottom, 10% from left] | [Minimap, ability icons] | [2] | [Navigation and ability readout. Small, non-intrusive.] |
|
||||
| [Bottom Center] | [Bottom edge, centered horizontally] | [Yes — 10% from bottom] | [Subtitles, tutorial prompts] | [2 — subtitle + tutorial may coexist] | [Highest-priority accessibility zone. Never place other elements here.] |
|
||||
| [Bottom Right] | [Bottom-right corner, within safe margin] | [Yes — 10% from bottom, 10% from right] | [Notification toasts, pick-up feedback] | [3 stacked] | [Transient notifications. Stack vertically. Oldest disappears first.] |
|
||||
|
||||
**Worked example — safe zone margins by platform**:
|
||||
|
||||
| Platform | Top | Bottom | Left | Right | Notes |
|
||||
|----------|-----|--------|------|-------|-------|
|
||||
| [PC — windowed] | [0% — no safe zone required] | [0%] | [0%] | [0%] | [But respect minimum resolution — elements must not crowd at 1280x720] |
|
||||
| [PC — fullscreen] | [3%] | [3%] | [3%] | [3%] | [Slight margin for 4K TV-connected PCs] |
|
||||
| [Console — TV] | [10%] | [10%] | [10%] | [10%] | [Action-safe zone for broadcast-spec TVs. Some TVs overscan beyond this.] |
|
||||
| [Steam Deck] | [5%] | [5%] | [5%] | [5%] | [Small screen; safe zone is smaller but crowding risk is higher] |
|
||||
| [Mobile — portrait] | [15% top] | [10% bottom] | [5%] | [5%] | [15% top avoids notch/camera cutout on most devices] |
|
||||
| [Mobile — landscape] | [5%] | [5%] | [15% left] | [15% right] | [Thumb placement on landscape — side zones are obscured by hands] |
|
||||
|
||||
---
|
||||
|
||||
## Section 4 — HUD Element Specifications
|
||||
|
||||
> **Why this section exists**: Each HUD element needs its own specification to be
|
||||
> built correctly. Ad-hoc implementation of HUD elements produces inconsistent
|
||||
> sizing, mismatched update frequencies, missing urgency states, and accessibility
|
||||
> failures. This section is the implementation brief for every element — fill it
|
||||
> completely before any element moves into development.
|
||||
|
||||
**Worked example — element overview table (4.1)**:
|
||||
|
||||
| Element Name | Zone | Always Visible | Visibility Trigger | Data Source | Update Frequency | Max Size (% screen W) | Min Readable Size | Overlap Priority | Accessibility Alt |
|
||||
|-------------|------|---------------|-------------------|-------------|-----------------|----------------------|------------------|-----------------|------------------|
|
||||
| [Health Bar] | [Top Left] | [Yes] | [N/A] | [PlayerStats] | [On value change] | [20%] | [120px wide] | [1 — highest] | [Numerical text label showing current/max: "80/100"] |
|
||||
| [Stamina Bar] | [Top Left] | [No — context] | [Show when consuming stamina; hide 3s after full] | [PlayerStats] | [Realtime during use] | [15%] | [80px wide] | [2] | [Numerical label, or hide if full (accessible assumption)] |
|
||||
| [Shield Indicator] | [Top Left] | [No — context] | [Show when shield is active or recently hit] | [PlayerStats] | [On value change] | [20%] | [120px wide] | [3] | [Numerical label. Must not use color alone — add shield icon.] |
|
||||
| [Ammo Counter] | [Top Right] | [No — context] | [Show when weapon is equipped; hide when unarmed] | [WeaponSystem] | [On fire / on reload] | [10%] | ["88/888" readable at game's min resolution] | [4] | [Text-only fallback: "32 / 120"] |
|
||||
| [Minimap] | [Bottom Left] | [Yes] | [N/A — but suppressed in cinematic mode] | [NavigationSystem] | [Realtime] | [18%] | [150x150px] | [5] | [Cardinal direction compass strip as fallback; must be toggleable] |
|
||||
| [Quest Objective] | [Top Center] | [No — context] | [Show on objective change; show when near objective location; hide after 5s] | [QuestSystem] | [On event] | [30%] | [Legible at body text size] | [6] | [Read aloud on objective change via screen reader] |
|
||||
| [Crosshair] | [Center] | [No — context] | [Show when ranged weapon equipped; hide in melee or unarmed] | [WeaponSystem / AimSystem] | [Realtime] | [3%] | [12px diameter minimum] | [1 — center zone priority] | [Reduce motion: static crosshair only. Option to enlarge.] |
|
||||
| [Interaction Prompt] | [Center] | [No — context] | [Show when player is within interaction range of an interactive object] | [InteractionSystem] | [On enter/exit interaction range] | [15%] | [24px icon + readable text] | [2 — center zone] | [Text description of interaction always present, not icon-only] |
|
||||
| [Subtitles] | [Bottom Center] | [No — always on when dialogue plays, if setting enabled] | [Show during any voiced line or ambient dialogue] | [DialogueSystem] | [Per dialogue line] | [60%] | [Minimum 24px font] | [1 — highest in zone] | [This IS the accessibility feature — see Section 8 for subtitle spec] |
|
||||
| [Damage Numbers] | [World-space / anchored to entity] | [No — context] | [Show on any damage event; duration 800ms] | [CombatSystem] | [On event] | [5% per number] | [18px minimum] | [3] | [Option to disable; numbers can overwhelm for photosensitive players] |
|
||||
| [Status Effect Icons] | [Top Left — below health bar] | [No — context] | [Show when any status effect is active on player] | [StatusSystem] | [On effect add/remove] | [3% per icon] | [24px per icon] | [3] | [Icon + text label on hover/focus. Never icon-only.] |
|
||||
| [Notification Toast] | [Bottom Right] | [No — event-driven] | [On loot, XP gain, achievement, quest update] | [Multiple — see Section 6] | [On event] | [25%] | [Legible at body text size] | [7 — lowest] | [Queued; never overlapping. Read by screen reader if subtitle mode on.] |
|
||||
|
||||
**Worked example — element detail blocks (4.2)**:
|
||||
|
||||
---
|
||||
|
||||
**Health Bar**
|
||||
|
||||
- Visual description: [Horizontal fill bar. Left-to-right fill direction. Segmented at 25/50/75% to aid reading at a glance. Background: dark semi-transparent (40% opacity). Fill color: context-dependent — see Urgency States.]
|
||||
- Data displayed: [Current HP as fill percentage. Numerical value displayed as text below bar at all times: "80 / 100".]
|
||||
- Update behavior: [Bar fill decreases or increases smoothly using a lerp over 150ms per change. Large damage (>25% single hit) triggers a brief flash (1 frame white, then drain).]
|
||||
- Urgency states:
|
||||
- Normal (>50% HP): [Green fill, no special behavior]
|
||||
- Caution (25–50% HP): [Yellow fill, low warning pulse every 4 seconds]
|
||||
- Critical (<25% HP): [Red fill, persistent slow pulse (1 Hz), vignette appears at screen edges]
|
||||
- Zero (0% HP): [Bar empties and turns grey; death state begins]
|
||||
- Interaction: [Display only. Not interactive. Player cannot click, hover, or focus this element as an action target.]
|
||||
- Player customization: [Opacity adjustable (see Section 7 Tuning Knobs). Can be repositioned to any corner by player in accessibility settings.]
|
||||
|
||||
---
|
||||
|
||||
**Minimap**
|
||||
|
||||
- Visual description: [Circular mask, radius = 75px at reference resolution 1920x1080. Player icon at center. North always up unless player has unlocked "Rotate minimap" setting. Range = configurable, default 80 world units radius.]
|
||||
- Data displayed: [Player position, nearby enemies (if detection perk unlocked), quest markers within range, points of interest icons, traversal obstacles (walls, drops).]
|
||||
- Update behavior: [Realtime. Updates every frame. Enemy icons fade in/out as they enter/leave detection range over 300ms.]
|
||||
- Urgency states: [None for the map itself. Enemy icons turn red when they are in combat-alert state.]
|
||||
- Interaction: [Not interactive in-game. Press dedicated Map button to open the full map screen (separate UX spec).]
|
||||
- Player customization: [Size: S/M/L (70/90/110px radius). Opacity: 30–100%. Rotation: locked-north or player-relative. Can be disabled entirely (compass strip shows as fallback).]
|
||||
|
||||
---
|
||||
|
||||
## Section 5 — HUD States by Gameplay Context
|
||||
|
||||
> **Why this section exists**: The HUD is not a static overlay — it is a dynamic
|
||||
> system that must adapt to what the player is doing. A HUD designed only for
|
||||
> standard gameplay will look wrong in cutscenes, feel cluttered in exploration,
|
||||
> and occlude critical information in boss fights. This section defines the
|
||||
> transformations the HUD undergoes in each gameplay context. It is also the spec
|
||||
> for the system that manages HUD visibility — the HUD state machine.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Context | Elements Shown | Elements Hidden | Elements Modified | Transition Into This State |
|
||||
|---------|---------------|-----------------|------------------|---------------------------|
|
||||
| [Exploration — no threats] | [Minimap, Quest Objective (faded, 60%), Subtitles (if active)] | [Ammo Counter, Crosshair, Damage Numbers, Status Effects (if none active)] | [Health Bar fades to 40% opacity — visible but not dominant] | [Fade transition, 500ms, when no enemies detected for 10s] |
|
||||
| [Combat — active threat] | [Health Bar (full opacity), Stamina Bar (when used), Ammo Counter, Crosshair, Damage Numbers, Status Effects, Enemy Health Bars] | [Quest Objective (temporarily hidden), Notification Toasts (paused queue)] | [Minimap scales down 15% and raises opacity to 100%] | [Immediate snap in on first enemy detection — no fade. Combat readiness requires instant info.] |
|
||||
| [Dialogue / Cutscene] | [Subtitles, Dialogue speaker name] | [All gameplay HUD elements: health, ammo, minimap, crosshair, damage numbers] | [N/A] | [All gameplay elements fade out over 300ms when cutscene flag is set] |
|
||||
| [Cinematic (scripted camera sequence)] | [Subtitles only] | [Everything else including speaker name] | [Letterbox bars appear (if applicable to this game's style)] | [Immediate on cinematic flag; letterbox slides in from top/bottom over 400ms] |
|
||||
| [Inventory / Menu open] | [None — inventory renders full-screen or as overlay] | [All HUD elements] | [Game world visible but paused behind inventory screen] | [All HUD elements hide over 150ms as menu opens] |
|
||||
| [Death / Respawn pending] | [Death screen overlay — separate spec] | [All gameplay HUD elements] | [Screen desaturates and darkens over 800ms] | [Death state begins when HP reaches 0 — HUD elements fade over 600ms] |
|
||||
| [Loading / Transition] | [Loading indicator, tip text] | [All gameplay HUD elements] | [N/A] | [Instant on level transition trigger] |
|
||||
| [Tutorial — new mechanic] | [Standard context HUD + Tutorial Prompt overlay] | [Nothing additional hidden] | [Tutorial prompt dims background subtly to draw attention to prompt] | [Tutorial system fires ShowTutorial event; prompt fades in over 200ms] |
|
||||
| [Boss Encounter] | [Boss health bar appears (large, bottom of screen or top center), all combat elements] | [Quest Objective] | [Boss bar renders in a distinct visual style — must not be confused with player health] | [Boss health bar slides in on boss encounter trigger over 400ms] |
|
||||
|
||||
---
|
||||
|
||||
## Section 6 — Information Hierarchy
|
||||
|
||||
> **Why this section exists**: Not all HUD information is equally important. When
|
||||
> screen space is limited, when the player is under high stress, or when elements
|
||||
> compete for the same zone, there must be a principled priority order that governs
|
||||
> which elements survive and which get suppressed. This section formalizes that
|
||||
> hierarchy so it can be enforced systematically and not just "feels obvious" decisions
|
||||
> made at implementation time.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Element | Priority Tier | Reasoning | What Replaces It If Hidden |
|
||||
|---------|--------------|-----------|---------------------------|
|
||||
| [Subtitles] | [MUST KEEP — never hide during dialogue] | [Accessibility requirement. Legal requirement in some markets. Story clarity.] | [N/A — nothing replaces subtitles] |
|
||||
| [Health Bar] | [MUST KEEP — during any state where the player can be damaged] | [Without health visibility, survival decisions become impossible] | [Auditory cues (heartbeat, breathing) supplement but do not replace] |
|
||||
| [Crosshair] | [MUST KEEP — while aiming with a ranged weapon] | [Targeting without a crosshair is a precision failure, not a difficulty feature] | [Alternative: dot-only mode for minimalists; never fully hidden while aiming] |
|
||||
| [Interaction Prompt] | [MUST KEEP — when player is in interaction range] | [Without it, interactive objects are invisible to the player] | [Environmental visual cues can supplement but interaction affordance must be explicit] |
|
||||
| [Ammo Counter] | [SHOULD KEEP] | [Low ammo decisions (switch weapon, reload) require awareness; can be contextual] | [Auditory "click" on empty chamber is acceptable fallback for experienced players] |
|
||||
| [Minimap] | [SHOULD KEEP] | [Navigation requires spatial awareness; loss forces repeated map opens] | [Compass strip (simplified directional indicator) is acceptable fallback] |
|
||||
| [Status Effects] | [SHOULD KEEP — while active] | [Active debuffs change what actions are viable; invisible debuffs feel unfair] | [Character animation states can partially communicate status effects (limping, sparks)] |
|
||||
| [Quest Objective] | [CAN HIDE] | [Player can hold objective in memory for extended periods; contextual is correct default] | [Player remembers objective from context] |
|
||||
| [Damage Numbers] | [CAN HIDE] | [Feedback element, not decision-critical. Many players turn these off.] | [Hit sounds and enemy reactions communicate hit registration] |
|
||||
| [Notification Toasts] | [CAN HIDE in high-intensity moments] | [Mid-combat "You gained 50 XP" is noise, not signal. Queue and show after combat.] | [Queue held and released when combat ends] |
|
||||
| [Combo Counter] | [ALWAYS HIDE when combo resets or player is not attacking] | [Stale combo information is actively misleading] | [N/A — simply hidden] |
|
||||
|
||||
---
|
||||
|
||||
## Section 7 — Visual Budget
|
||||
|
||||
> **Why this section exists**: Without explicit budget constraints, HUD elements
|
||||
> accumulate until the game world is nearly invisible. These numbers are hard limits,
|
||||
> not guidelines. Every element addition that would breach a limit requires explicit
|
||||
> approval and must displace or reduce an existing element.
|
||||
|
||||
> **How to apply these budgets**: For every new HUD element proposed during
|
||||
> production, require the proposer to state (1) which budget line it affects,
|
||||
> (2) what the new total will be, and (3) what existing element will be reduced or
|
||||
> made contextual to stay within budget. "It's a small icon" is not an analysis.
|
||||
|
||||
---
|
||||
|
||||
## Section 8 — Feedback & Notification Systems
|
||||
|
||||
> **Why this section exists**: Notifications are the most frequently-added and
|
||||
> worst-controlled part of most HUDs. Every system wants to tell the player
|
||||
> something. Without explicit rules about notification priority, stacking limits,
|
||||
> and queue behavior, the notification zone becomes a firehose of overlapping
|
||||
> toasts that players learn to ignore entirely. This section establishes the
|
||||
> notification contract for all systems.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Notification Type | Trigger System | Screen Position | Duration (ms) | Animation In / Out | Max Simultaneous | Priority | Queue Behavior | Dismissible? |
|
||||
|------------------|---------------|-----------------|--------------|-------------------|-----------------|----------|---------------|-------------|
|
||||
| [Item Pickup] | [InventorySystem] | [Bottom Right — toast] | [2000] | [Slide in from right 200ms / fade out 300ms] | [3 stacked] | [Low] | [FIFO queue; older toasts pushed up as new ones enter] | [No — auto-dismiss] |
|
||||
| [XP Gain] | [ProgressionSystem] | [Bottom Right — toast, below item toasts] | [1500] | [Fade in 150ms / fade out 300ms] | [1 — XP messages merge: "XP +150"] | [Very Low — suppress during combat, queue for post-combat] | [Combat-aware queue] | [No] |
|
||||
| [Level Up] | [ProgressionSystem] | [Center screen — persistent until dismissed] | [Persistent — requires input to dismiss] | [Scale up from 80% + fade in 400ms] | [1] | [High — interrupts normal toasts] | [Pauses all other notifications until dismissed] | [Yes — any input] |
|
||||
| [Quest Update] | [QuestSystem] | [Top Center] | [4000] | [Slide down from top 250ms / fade out 400ms] | [1 — top center is single-message zone] | [Medium] | [If quest update arrives while previous is visible, extend duration by 2000ms; do not stack] | [No] |
|
||||
| [Objective Complete] | [QuestSystem] | [Top Center] | [3000] | [Same as Quest Update but with additional completion sound] | [1] | [Medium-High — preempts Quest Update] | [Preempts any queued top-center message] | [No] |
|
||||
| [Critical Warning (low health, hazard)] | [CombatSystem / EnvironmentSystem] | [Screen edge vignette + text at center-bottom] | [Persistent while condition active] | [Fade in 200ms; fades out 500ms when condition clears] | [1 per warning type] | [Critical — never suppressed] | [Renders immediately, bypasses all queues] | [No] |
|
||||
| [Achievement Unlocked] | [AchievementSystem] | [Bottom Right — distinct from item toasts] | [4000] | [Slide in from right with icon expansion 300ms / fade out 400ms] | [1] | [Low] | [Queues behind item toasts; never more than one achievement toast at a time] | [No] |
|
||||
| [Hint / Tutorial] | [TutorialSystem] | [Bottom Center] | [Persistent — until player performs the action or dismisses] | [Fade in 300ms] | [1] | [Medium] | [Only one tutorial hint at a time; queue others] | [Yes — B button / Esc] |
|
||||
|
||||
**Worked example — notification queue rules**:
|
||||
1. Combat-aware queue: notifications tagged as Low priority are queued, not displayed, when the player is in combat state. The queue is flushed in a batch when the player exits combat, with a max of 3 items displayed in sequence.
|
||||
2. Merge rule: identical notification types that fire within 500ms of each other are merged into a single notification with a combined value (e.g., "Item Pickup x3" rather than three separate toasts).
|
||||
3. Critical notifications (health warning, environmental hazard) are never queued, never merged, and always displayed immediately regardless of combat state or existing notifications.
|
||||
|
||||
---
|
||||
|
||||
## Section 9 — Platform Adaptation
|
||||
|
||||
> **Why this section exists**: A HUD designed at 1920x1080 on a monitor may be
|
||||
> illegible on a 55-inch TV at 4K, broken at 1280x720 on Steam Deck, or hidden
|
||||
> behind a notch on mobile. Platform adaptation is not optional post-ship work —
|
||||
> it is a design requirement that must be specified before implementation so the
|
||||
> architecture can support it from the start. Every platform listed here requires
|
||||
> explicit layout testing before certification.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Platform | Safe Zone | Resolution Range | Input Method | HUD-Specific Notes |
|
||||
|----------|-----------|-----------------|-------------|-------------------|
|
||||
| [PC — Windows, 1920x1080 reference] | [3% margin] | [1280x720 min to 3840x2160 max] | [Mouse + keyboard, controller optional] | [HUD must scale correctly at all resolutions. Test at 1280x720 — minimum before cert. Consider ultrawide (21:9) — minimap must not stretch.] |
|
||||
| [PC — Steam Deck, 1280x800] | [5% margin] | [Fixed 1280x800] | [Controller + touchscreen] | [Smaller screen means minimum text sizes are critical. Test ALL elements at this resolution. Touch targets irrelevant (controller-only by default).] |
|
||||
| [PlayStation 5 / Xbox Series X] | [10% margin] | [1080p to 4K] | [Controller] | [Console certification requires TV safe zone compliance. Action-safe is 90% of screen area. Test on a real TV, not a monitor — overscan behavior differs.] |
|
||||
| [Mobile — iOS / Android] | [15% top, 10% other sides] | [360x640 min to 414x896 common] | [Touch] | [Notch/camera cutout avoidance at top. Bottom home indicator zone avoidance. Portrait and landscape layouts may differ significantly — specify both.] |
|
||||
|
||||
---
|
||||
|
||||
## Section 10 — Accessibility (HUD Specific)
|
||||
|
||||
> **Why this section exists**: HUD accessibility failures are the most visible
|
||||
> accessibility failures in games — players encounter the HUD in every session,
|
||||
> in every gameplay moment. Color-blind failures, illegible text at minimum scale,
|
||||
> and inability to disable distracting animations are among the top accessibility
|
||||
> complaints in game reviews. This section defines HUD-specific requirements; refer
|
||||
> to the project's `design/accessibility-requirements.md` for the full project standard.
|
||||
|
||||
**Worked example — colorblind modes table (10.1)**:
|
||||
|
||||
| Element | Color-Only Information Risk | Colorblind Mode Fix |
|
||||
|---------|----------------------------|---------------------|
|
||||
| [Health bar fill] | [Red = low health uses red/green distinction] | [Add icon pulse + vignette as non-color indicators. Red fill is supplemental, not sole indicator.] |
|
||||
| [Damage numbers] | [Red = taken, green = healed] | [Add minus (-) prefix for damage, plus (+) for healing. Symbols, not color.] |
|
||||
| [Enemy health bars] | [If colored by faction or threat level] | [Add text label or icon badge for faction/threat level. Never color-only.] |
|
||||
| [Status effect icons] | [If icon tint communicates status type] | [All status icons must have distinct shapes, not just distinct colors. Shape encodes meaning; color is secondary.] |
|
||||
| [Minimap icons] | [If player vs. enemy vs. objective distinguished by color] | [Distinct icon shapes: circle = player, triangle = enemy, star = objective. Color supplements shape.] |
|
||||
|
||||
**Authoring the text scaling narrative (10.2)**:
|
||||
|
||||
[Describe what happens when the player sets the UI text scale to 150% (the maximum required for your Accessibility Tier). Which elements reflow? Which elements clip? Which elements are architecturally blocked from scaling (e.g., fixed-size canvases)?
|
||||
|
||||
Example: "Health bar numerical label grows with text scale — bar expands slightly to accommodate. Quest objective text wraps at 150% scale — verify Top Center zone can accommodate two-line objectives. Damage numbers do not scale (they are world-space, not screen-space) — this is an accepted limitation documented here."]
|
||||
|
||||
**Worked example — text scaling test matrix (10.2)**:
|
||||
|
||||
| Element | 100% (baseline) | 125% | 150% | Overflow behavior |
|
||||
|---------|----------------|------|------|-------------------|
|
||||
| [Health bar label] | [Pass] | [Pass] | [TBD] | [Bar expands; does not overlap stamina bar] |
|
||||
| [Quest objective text] | [Pass] | [TBD] | [TBD] | [Wraps to second line; zone height expands] |
|
||||
| [Notification toast text] | [Pass] | [TBD] | [TBD] | [Toast width expands to max 35% screen width, then wraps] |
|
||||
| [Subtitle text] | [Pass] | [TBD] | [TBD] | [Dedicated subtitle zone — must accommodate scale] |
|
||||
|
||||
**Worked example — motion sensitivity table (10.3)**:
|
||||
|
||||
| Animation / Motion Element | Severity | Disabled by Reduced Motion Setting? | Replacement Behavior |
|
||||
|---------------------------|----------|-------------------------------------|---------------------|
|
||||
| [Health bar low-HP pulse] | [Mild] | [Yes] | [Solid fill, no pulse. Vignette remains as it is less likely to trigger sensitivity.] |
|
||||
| [Screen edge vignette] | [Moderate] | [Optional — separate toggle] | [Replace with static darkened corners at 30% opacity] |
|
||||
| [Damage numbers float upward] | [Mild] | [Yes] | [Instant appear/disappear in place, no float] |
|
||||
| [Notification toast slide-in] | [Mild] | [Yes] | [Instant appear at final position] |
|
||||
| [Level up center animation] | [High] | [Yes — required] | [Static level up card, no scale animation, no particle effects] |
|
||||
| [Combo counter scale pulse] | [Mild] | [Yes] | [Number increments without scale animation] |
|
||||
|
||||
---
|
||||
|
||||
## Section 11 — Tuning Knobs
|
||||
|
||||
> **Why this section exists**: HUD behavior should be data-driven to the same degree
|
||||
> as gameplay systems. Values that are hardcoded are values that require an engineer
|
||||
> to change. Values that are in config can be tuned by a designer or adjusted for
|
||||
> player preferences. Document all tunable parameters before implementation so the
|
||||
> programmer knows which values to externalize.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Parameter | Current Value | Range | Effect of Increase | Effect of Decrease | Player Adjustable? | Notes |
|
||||
|-----------|-------------|-------|-------------------|-------------------|-------------------|-------|
|
||||
| [Notification display duration (default)] | [2000ms] | [500ms – 5000ms] | [Toasts persist longer — less likely to be missed, more screen clutter] | [Toasts disappear faster — cleaner, higher miss risk] | [No — but player can adjust verbosity level] | [Per-type overrides in Section 8 take precedence] |
|
||||
| [Notification queue max size] | [8] | [3 – 15] | [More messages preserved but queue takes longer to clear] | [Older messages dropped earlier] | [No] | [Expand if playtesting reveals important messages being lost] |
|
||||
| [Health bar low-HP pulse frequency] | [1 Hz] | [0.5 – 2 Hz] | [More urgent feeling — can become fatiguing] | [Calmer — may fail to communicate urgency] | [No — but Reduced Motion disables it] | [Linked to accessibility setting] |
|
||||
| [Combat HUD reveal duration] | [0ms (instant)] | [0 – 300ms] | [Softer reveal — feels less jarring] | [Instant — highest responsiveness] | [No] | [Keep at 0ms — combat information must be instant] |
|
||||
| [Exploration HUD fade-out delay] | [10000ms (10s after last threat)] | [3000 – 30000ms] | [HUD fades sooner — cleaner exploration] | [HUD stays longer — more reassurance] | [No] | [Tune based on playtest; 10s is a starting estimate] |
|
||||
| [Minimap range (world units visible)] | [80] | [40 – 200] | [More map context visible] | [Tighter local view] | [Yes — Small/Medium/Large preset] | [Exposed as S/M/L, not raw unit value] |
|
||||
| [Minimap size (px radius at 1080p)] | [75] | [50 – 120] | [Larger map, more screen space consumed] | [Smaller, less intrusive] | [Yes — S/M/L preset] | [Three sizes exposed to player] |
|
||||
| [Damage number duration (ms)] | [800] | [400 – 1500] | [Numbers linger longer — easier to read, more cluttered] | [Numbers clear faster — cleaner, harder to parse] | [No] | [Tune based on visual noise in dense combat] |
|
||||
| [Global HUD opacity] | [100%] | [0 – 100%] | [Fully visible] | [Fully hidden] | [Yes — opacity slider in Accessibility settings] | [0% = full HUD off; some players prefer this] |
|
||||
|
||||
---
|
||||
|
||||
## Section 12 — Acceptance Criteria
|
||||
|
||||
> **Why this section exists**: These criteria are the certification checklist for the
|
||||
> HUD. Every item must pass before the HUD can be marked Approved. QA must be able
|
||||
> to verify each item independently.
|
||||
|
||||
---
|
||||
|
||||
## Section 13 — Open Questions
|
||||
|
||||
**Worked example questions**:
|
||||
|
||||
| Question | Owner | Deadline | Resolution |
|
||||
|----------|-------|----------|-----------|
|
||||
| [e.g., Should the minimap show enemy positions by default, or only after a detection skill is unlocked?] | [systems-designer + ui-designer] | [Sprint 5, Day 2] | [Pending — depends on progression GDD decision] |
|
||||
| [e.g., Does the game have a boss health bar, or do bosses use the standard enemy health bar? Bosses need a visually distinct treatment if they are significantly more important than normal enemies.] | [game-designer] | [Sprint 5, Day 1] | [Pending] |
|
||||
| [e.g., Damage numbers: diegetic (floating in world space, occluded by geometry) or screen space (always readable, overlaid on HUD layer)?] | [ui-designer + lead-programmer] | [Sprint 4, Day 5] | [Pending — architecture decision affects rendering layer choice] |
|
||||
| [e.g., Mobile portrait vs. landscape: does the game support both orientations? If yes, each requires its own zone layout.] | [producer] | [Sprint 3, Day 3] | [Pending — platform scope decision required first] |
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
> Authoring guidance for interaction-pattern-library.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
> Covers: **Game-Specific UI Patterns** — full reference specifications for Inventory Slot, Ability / Skill Icon, Health / Resource Bar, Dialogue Box, Context Action Prompt, Damage Number.
|
||||
|
||||
## Game-Specific UI Patterns
|
||||
|
||||
---
|
||||
|
||||
#### Inventory Slot
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: Every item container in the inventory grid. Empty slots, populated
|
||||
slots, equipped slots, locked slots. The slot is the frame; the item icon is the
|
||||
content.
|
||||
|
||||
**States**:
|
||||
|
||||
| State | Visual | Notes |
|
||||
|-------|--------|-------|
|
||||
| Empty | Subtle slot border, no content. Not the same as disabled. Empty slots are interactable (receive items). | Avoid fully invisible empty slots — players lose track of grid dimensions |
|
||||
| Populated | Item icon fills 80% of slot area. Stack count bottom-right (if applicable). Quality border (colorblind-safe — icon + color). Equipped badge (top-right, if equipped). | |
|
||||
| Focused | Focus ring. Tooltip appears after 300ms. | |
|
||||
| Selected | Thicker or contrasting border. Used when multi-select is supported. | |
|
||||
| Drag source | Slot dims, drag ghost follows pointer. | See Grid Item for full drag spec |
|
||||
| Locked | Padlock icon overlay. No interaction. May show item at 50% opacity behind lock. | Used for locked loadout slots, DLC content, etc. |
|
||||
| Highlighted | Animated border glow (pulsing). Used for quest-relevant items or newly acquired items. | Respect motion reduction — replace pulse with a static badge |
|
||||
| Cooldown overlay | Radial fill overlay from 12 o'clock, clockwise, depleting as cooldown expires. | Only applicable if slots represent active items with cooldowns |
|
||||
|
||||
**Accessibility**: Stack counts and quality tiers must have text or icon alternatives to color coding. Tooltip is the primary accessibility mechanism — ensure it is reachable by keyboard and screen reader. Locked slots must announce "locked" to screen readers.
|
||||
|
||||
**Implementation Notes**: [Godot: Custom `Control` node. Quality border implemented as a `StyleBoxFlat` swapped based on rarity — avoid using `modulate` color for quality, as it affects the icon color. Drag and drop implemented via `get_drag_data()` and `can_drop_data()` / `drop_data()` override methods.]
|
||||
|
||||
---
|
||||
|
||||
#### Ability / Skill Icon
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: Ability buttons in the HUD ability bar, skill tree nodes, and
|
||||
any context where an ability must show availability state.
|
||||
|
||||
**States**:
|
||||
|
||||
| State | Visual | Notes |
|
||||
|-------|--------|-------|
|
||||
| Available | Full opacity icon. Keybinding label below. | |
|
||||
| On cooldown | Radial overlay depleting clockwise from 12 o'clock. Remaining time shown as a number in the center when > 2 seconds remain. | |
|
||||
| Charges remaining | Charge pip indicators below icon (e.g., 3 filled circles = 3 charges). Number alternative for screen readers. | |
|
||||
| Out of resource | Icon desaturates to ~20%. Border dims. Keybinding label dims. Distinct from cooldown — resource-gated, not time-gated. | |
|
||||
| Locked / not unlocked | Icon silhouette only (no full art visible). Padlock badge. May show unlock condition in tooltip. | |
|
||||
| Active / channeling | Pulsing border. Radial fill shows channel duration remaining. | |
|
||||
| Just activated | Brief scale 0.9x then spring to 1.0x (overshoot to 1.05x). | Example: Guild Wars 2 and Path of Exile both use press-depress animations on ability use to confirm activation. Respect motion reduction. |
|
||||
|
||||
**Accessibility**: All cooldown/charge information must have a numeric value (screen reader cannot parse radial overlays). The cooldown timer number satisfies this. Ability names and descriptions must be exposed to screen readers via tooltip.
|
||||
|
||||
**Implementation Notes**: [Godot: Custom `TextureButton` subclass with overlay
|
||||
`Control` nodes for cooldown radial and charge pips. The cooldown radial uses a
|
||||
custom shader on a `ColorRect` rotating a mask — or implement with a
|
||||
`ProgressBar` styled as circular if engine supports it. Verify against
|
||||
engine-reference/godot/ for Godot 4.6 shader support for this pattern.]
|
||||
|
||||
---
|
||||
|
||||
#### Health / Resource Bar
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: Any continuously varying value in the HUD that represents a
|
||||
critical player resource. Health, mana, stamina, shield, fuel.
|
||||
|
||||
**States and behaviors**:
|
||||
|
||||
| Event | Visual | Audio | Duration |
|
||||
|-------|--------|-------|---------|
|
||||
| Value decrease (damage) | Fill shrinks. Brief "damage flash" on the fill (white or red flash). Ghost bar lingers at previous value and drains to new value over 0.5s ("damage indicator"). | [Damage taken sound — varies by amount] | Instant decrease, 500ms ghost bar drain |
|
||||
| Value increase (heal) | Fill grows. Brief heal color flash (green — ensure colorblind safe with icon/glow backup). | [Heal sound] | 300ms ease-in |
|
||||
| Below 25% threshold | Fill changes color to warning state. Border pulses (or static badge in motion reduction mode). Optional: heartbeat audio cue (paired with visual if audio is sole signal). | [Low health sound — loops until above threshold] | Continuous |
|
||||
| At zero | Bar empty. Optional: bar shakes briefly. Death/depletion event fires. | [Death/depletion sound] | 200ms shake |
|
||||
| Maximum | Fill at 100%, brief glow. | — | 200ms |
|
||||
| Overflow (shield) | A separate bar segment appears beyond the natural fill area, in shield color. | [Shield gain sound] | 200ms |
|
||||
|
||||
**Accessibility**: The current value must be accessible as a number (tooltip or persistent display, or both). Color-coded threshold states must have non-color backups (icon, flashing, or audio visual warning). Warning state at 25% must have a visual signal independent of the color change.
|
||||
|
||||
**Implementation Notes**: [Godot: Two overlapping `ProgressBar` nodes for ghost
|
||||
bar effect — back bar holds previous value (drains via Tween), front bar holds
|
||||
current value (updates instantly). Threshold states trigger `StyleBoxFlat` swaps
|
||||
on the front bar. Ghost bar Tween duration is tunable as a designer parameter.]
|
||||
|
||||
---
|
||||
|
||||
#### Dialogue Box
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: NPC conversation, voiced narrative dialogue, tutorial text
|
||||
delivered through a character. All dialogue that has a speaker.
|
||||
|
||||
**Structure**: Speaker portrait or name tag (top of box or left side). Dialogue text body. Continue/advance prompt (bottom right). Optional: skip-all button, voice acting indicator, subtitle indicator.
|
||||
|
||||
**States and behaviors**:
|
||||
|
||||
| State | Visual | Input | Response | Duration |
|
||||
|-------|--------|-------|----------|---------|
|
||||
| Line entering | Text reveals character-by-character (typewriter effect). Or: text fades in at full speed if accessibility option set. | — | — | Speed: configurable in accessibility settings |
|
||||
| Revealing | Text animating in. Continue prompt hidden or pulsing at slow opacity. | [Any advance input] | Skip to end of current line instantly (show full line, stop typewriter) | Immediate |
|
||||
| Line complete | Full line shown. Continue prompt visible and animated. | — | — | — |
|
||||
| Advancing to next line | Continue prompt hides. Text fades out or wipes. New line begins. | [Any advance input] — Enter / A / Cross / Space / mouse click | Advance | 100ms transition |
|
||||
| Choices appearing | Choice buttons appear below dialogue text. Continue prompt hidden. Navigation focus moves to first choice. | D-pad / keyboard to select, Enter / A / Cross to confirm | Select choice | 150ms enter animation |
|
||||
| Closing | Box fades out | Final line advanced | Return control to player | 200ms |
|
||||
| Skipping all (if supported) | Brief confirmation prompt: "Skip dialogue?" | Dedicated skip button | Skip to post-dialogue state | — |
|
||||
|
||||
**Accessibility**: Subtitles are always enabled by default for all voiced dialogue. Typewriter animation speed is a user setting (see accessibility-requirements.md). The dialogue box must not auto-advance — players must control pacing. Speaker name is always shown. All choice buttons must be navigable by keyboard and gamepad. Choices must be accessible to screen readers with position announced.
|
||||
|
||||
**Implementation Notes**: [Godot: `RichTextLabel` with `bbcode_enabled` for
|
||||
formatting. Typewriter effect via `visible_characters` property animated by a
|
||||
`Timer`. Bind the advance input to a function that either skips typewriter
|
||||
(sets `visible_characters = -1`) or advances the dialogue state. Speaker name
|
||||
displayed in a separate `Label` above or beside the box. Dialogue data loaded from
|
||||
JSON or a dedicated dialogue format (e.g., Dialogic, Yarn Spinner for Godot).]
|
||||
|
||||
---
|
||||
|
||||
#### Context Action Prompt
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: A prompt that appears near an interactable game object indicating
|
||||
what the player can do. "Press [A] to open chest." "Hold [E] to pick up." Appears
|
||||
when the player enters the interaction zone, disappears when they leave.
|
||||
|
||||
**States**:
|
||||
|
||||
| State | Visual | Notes |
|
||||
|-------|--------|-------|
|
||||
| Appearing | Fades in and rises 8px from object anchor point. | Respect motion reduction — fade only, no rise |
|
||||
| Idle | Platform-correct button icon + action label. Icon matches current input method (updates if player switches). | Always show platform-correct icon — do not hardcode "Press A" for all platforms |
|
||||
| Holding (for hold inputs) | Radial fill on the button icon shows hold progress. Label changes to active verb ("Opening..."). | |
|
||||
| Cannot interact (blocked) | Icon dims. Label shows reason if known ("Too heavy", "Need key"). | Optional — only show blocked state if the reason is meaningful to the player |
|
||||
| Disappearing | Fades out. | Triggered when player exits interaction zone |
|
||||
|
||||
**Accessibility**: The button icon must be accompanied by a text label — do not rely on icon alone (some players use custom button labels or adaptive controllers with non-standard icons). The prompt must be positioned to not overlap character health or critical HUD information.
|
||||
|
||||
**Implementation Notes**: [Godot: Attach as a `Node3D` child (or `Node2D` child in 2D) of the interactable object. Use a `BillboardMesh` or a `SubViewport` with a UI scene for 3D games — this keeps the prompt facing the camera without code. Update the button icon texture based on `Input.get_joy_name()` or keyboard detection via `InputEventKey` vs `InputEventJoypadButton`. Hold progress implemented as an `AnimationPlayer` or `Tween` on a radial mask shader.]
|
||||
|
||||
---
|
||||
|
||||
#### Damage Number
|
||||
|
||||
**Category**: Game-Specific
|
||||
**Status**: Draft
|
||||
**When to Use**: Floating feedback numbers above combat participants. Normal
|
||||
damage, critical damage, healing, miss.
|
||||
|
||||
**Variants**:
|
||||
|
||||
| Variant | Visual | Notes |
|
||||
|---------|--------|-------|
|
||||
| Normal damage | White number, normal weight, medium size. | |
|
||||
| Critical hit | Larger size (1.5x), bold weight, orange or yellow — verify colorblind safe. Brief scale impact (1.3x → 1.0x on appear). | Example: Path of Exile and Diablo IV both use scale-pop for crits to make them immediately recognizable by size alone, independent of color. |
|
||||
| Healing | Green (verify colorblind safe — use + prefix and upward trajectory as non-color backups). | |
|
||||
| Miss / Evade | "MISS" text, grey, italic. Floats at smaller size. | |
|
||||
| Status damage (DoT) | Smaller size, distinct color matching the status effect. | |
|
||||
|
||||
**Behavior**: Numbers float upward from the hit location over 1.0 second. Numbers fade from 100% to 0% during the last 0.4 seconds. Multiple numbers from rapid hits stagger horizontally to avoid overlap. Maximum simultaneous damage numbers on screen: [define per game — typically 8-12 per character].
|
||||
|
||||
**Accessibility**: Damage numbers are purely supplementary feedback — they must never be the only way to understand combat state. Health bars are the authoritative source. Provide an option to disable damage numbers entirely (some players find them visually overwhelming). When disabled, the game must remain fully playable.
|
||||
|
||||
**Implementation Notes**: [Godot: Pool of `Label3D` (3D games) or `Label` (2D games)
|
||||
instances recycled via an object pool. Each instance is given a random small
|
||||
horizontal offset on spawn (±20px) to reduce overlap. Float animation via
|
||||
`Tween` on `position.y` and `modulate.a`. Critical hit scale-pop via Tween
|
||||
with `EASE_OUT` on scale followed by linear settle.]
|
||||
|
||||
---
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
> Authoring guidance for interaction-pattern-library.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
> Covers: **Navigation Patterns** (Screen Push / Pop / Replace, Focus Management, Escape / Cancel) and **Feedback and Loading Patterns** (Loading State, Empty State, Error State) — full reference specifications.
|
||||
|
||||
## Navigation Patterns
|
||||
|
||||
---
|
||||
|
||||
#### Screen Push / Pop / Replace
|
||||
|
||||
**Category**: Navigation
|
||||
**Status**: Draft
|
||||
|
||||
These three patterns define how screens enter and exit the navigation stack.
|
||||
|
||||
| Pattern | Trigger | Animation | Stack Behavior | Focus Behavior |
|
||||
|---------|---------|-----------|---------------|----------------|
|
||||
| Push | Navigate deeper (open submenu, open detail view) | New screen slides in from right. Previous screen slides left and dims. | Previous screen remains on stack | Focus moves to first interactive element on new screen |
|
||||
| Pop (Back) | Back button / Escape / B / Circle | Current screen slides right and exits. Previous screen slides in from left and brightens. | Current screen removed from stack | Focus returns to the element that triggered the Push |
|
||||
| Replace | Navigate to a peer screen (not child, not parent). Loading screen. | Fade out current, fade in new. No directional bias. | Current screen removed. New screen added. | Focus moves to first interactive element on new screen |
|
||||
|
||||
**Animation durations**: Push/Pop: 250ms ease-in-out. Replace: 200ms fade out + 200ms fade in.
|
||||
|
||||
**Motion reduction**: All slide animations become fades. Duration reduces to 100ms.
|
||||
|
||||
**Implementation Notes**: [Godot: Implement as a `ScreenManager` singleton managing
|
||||
a stack of `Control` scenes. `push(screen_scene)` instantiates and animates in.
|
||||
`pop()` animates out and frees. `replace(screen_scene)` calls pop then push without
|
||||
the intermediate stack state. Use `CanvasLayer` per screen to isolate input handling.
|
||||
Store the "return focus" element reference before pushing so it can be restored on pop.]
|
||||
|
||||
---
|
||||
|
||||
#### Focus Management
|
||||
|
||||
**Category**: Navigation
|
||||
**Status**: Draft
|
||||
|
||||
> Focus management is the most common keyboard and gamepad accessibility failure
|
||||
> in game UIs. These rules must be implemented consistently. A player should
|
||||
> never be in a state where they cannot see which element is focused, or where
|
||||
> Tab/D-pad produces no visible result.
|
||||
|
||||
| Rule | Description |
|
||||
|------|-------------|
|
||||
| Screen open | Focus is placed on the most logical interactive element — typically the Primary button, the first list item, or the last-focused element if the screen was previously visited. Never on a non-interactive element. |
|
||||
| Screen close / pop | Focus returns to the element that triggered the navigation (the button that opened the screen, the list item that was selected). If that element no longer exists, focus goes to the nearest preceding interactive element. |
|
||||
| Modal open | Focus is trapped inside the modal. See Modal Dialog pattern. |
|
||||
| Modal close | Focus returns to the element that triggered the modal. |
|
||||
| Element disabled | If the focused element becomes disabled, focus moves to the next available interactive element in the tab order. |
|
||||
| Element destroyed | If the focused element is removed from the scene, focus moves to the nearest preceding element in the tab order. |
|
||||
| Screen without interactive elements | Focus management is a no-op. Ensure back/cancel input still works. |
|
||||
| Tab key (keyboard) | Moves focus forward through interactive elements in document order (left to right, top to bottom). Shift+Tab moves backward. |
|
||||
| D-pad (gamepad) | Moves focus in the spatial direction pressed. Spatial navigation is preferred over strict tab order for gamepad. Never wrap focus between unrelated regions (e.g., Tab bar and content area should be separate navigation regions). |
|
||||
| Focus is always visible | Focus ring or equivalent focus indicator must ALWAYS be visible when an element is focused via keyboard or gamepad. Never suppress focus indicators. |
|
||||
|
||||
---
|
||||
|
||||
#### Escape / Cancel
|
||||
|
||||
**Category**: Navigation
|
||||
**Status**: Draft
|
||||
|
||||
> The "go back" action is the most-used navigation input in all menu systems.
|
||||
> It must be consistent across every screen with no exceptions.
|
||||
|
||||
| Platform | Input | Behavior |
|
||||
|----------|-------|---------|
|
||||
| PC (keyboard) | Escape | Close top-most modal / go back one screen in stack / if at root screen (main menu), open "quit?" confirmation |
|
||||
| PC (gamepad) | B (Xbox layout) / Circle (PS layout) | Same as Escape |
|
||||
| Xbox | B button | Same as Escape |
|
||||
| PlayStation | Circle button | Same as Escape |
|
||||
| Nintendo Switch | B button | Same as Escape (NOTE: Nintendo uses B for confirm in some first-party titles — verify platform convention for this release and document the decision) |
|
||||
|
||||
**Rules**: This input must never be overridden to do something other than "go back / cancel." If a screen has no back action (e.g., the game is paused and the player must make a choice), Escape does nothing or shows a "you must choose" message — it does not navigate away. Every screen must define its Escape behavior explicitly in its UX spec.
|
||||
|
||||
---
|
||||
|
||||
## Feedback and Loading Patterns
|
||||
|
||||
---
|
||||
|
||||
#### Loading State
|
||||
|
||||
**Category**: Feedback
|
||||
**Status**: Draft
|
||||
|
||||
| Scope | Pattern | Notes |
|
||||
|-------|---------|-------|
|
||||
| Full screen (initial load) | Full-screen loading screen with game art, progress bar (determinate if possible), tip text (optional). | Never use an empty black screen. Give the player something to read or look at. |
|
||||
| Full screen (level transition) | Fade to black, loading screen, fade from black to new scene. | The fade removes the pop of the previous scene disappearing. |
|
||||
| Component / inline | Spinner or skeleton placeholder replaces the loading component. Component does not shift layout when content loads. | Skeleton placeholder (grey boxes approximating content shape) is preferable to spinner for layout-heavy content — it prevents layout shift on load. |
|
||||
| Background / async | No visual indication unless operation exceeds 2 seconds. After 2 seconds, show a small spinner or toast. | Do not show loading indicators for operations that complete in under 2 seconds — the flash of an indicator is more disruptive than waiting. |
|
||||
|
||||
**Accessibility**: Loading states must announce to screen readers: "[Context] loading, please wait." Completion must announce "[Context] loaded." For full-screen loading, ensure the loading screen itself is navigable to screen readers — the tips text and any UI elements must be exposed.
|
||||
|
||||
---
|
||||
|
||||
#### Empty State
|
||||
|
||||
**Category**: Feedback
|
||||
**Status**: Draft
|
||||
|
||||
> Empty states are consistently the least-designed parts of game UIs. They are
|
||||
> the difference between a player feeling "this is where I'll store my items"
|
||||
> and "why is nothing here? did something break?" Every empty list and grid must
|
||||
> have a designed empty state. The empty state is not an error — it is a starting
|
||||
> point.
|
||||
|
||||
| Location | Empty State Content | Notes |
|
||||
|----------|--------------------|----|
|
||||
| Inventory (no items) | Icon (subtle, large, centered). Message: "Your inventory is empty." Sub-message: "Items you find on your journey will appear here." | Do not say "No items found" — "found" implies a failed search. |
|
||||
| Quest Log (no active quests) | Icon. Message: "No active quests." Sub-message: "Talk to characters marked with [quest marker icon] to start a quest." | Give the player a clear action. |
|
||||
| Achievements (none earned) | Icon. Message: "No achievements yet." List of hint achievements: "Try [Action] to earn your first achievement." | Gamified motivation, not just emptiness. |
|
||||
| Search results (no matches) | Icon. Message: "No results for '[search term]'." Sub-message: "Try a different search or [browse all]." | Mirror the search term back at them. Give an alternative action. |
|
||||
|
||||
**Rule**: Every empty state must include an icon, a message, and either a sub-message or an action button. A blank container with no explanation is never acceptable.
|
||||
|
||||
---
|
||||
|
||||
#### Error State
|
||||
|
||||
**Category**: Feedback
|
||||
**Status**: Draft
|
||||
|
||||
| Error Type | Pattern | Tone |
|
||||
|-----------|---------|------|
|
||||
| Input validation (form field) | Inline error message below the field. Error icon left of message. Red border on field (colorblind-safe with icon). | Neutral and specific — "Username must be 3-20 characters." Not "Invalid input." |
|
||||
| Operation failed (save error, network error) | Toast notification for non-critical failures. Modal Dialog for critical failures (save file cannot be written). | Calm and actionable — "Save failed. Check storage space." Not "FATAL ERROR." |
|
||||
| System error (crash, data corruption) | Full-screen error screen with error code, recovery options ("Restart Game," "Load last save"), and support contact. | Reassuring — acknowledge the problem, give the player agency. Never blame the player. |
|
||||
| Soft error (action cannot be performed) | Toast or inline message. | Explanatory — "Not enough gold" not "Action unavailable." |
|
||||
|
||||
**Principle**: Error messages are never the player's fault. They are the game telling the player what happened and what to do next. Remove the word "invalid" from all error messages — replace with specific explanations.
|
||||
|
||||
---
|
||||
+589
@@ -0,0 +1,589 @@
|
||||
> Authoring guidance for interaction-pattern-library.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
> Covers: **Standard Control Patterns** — full reference specifications for Button (Primary/Secondary/Destructive), Toggle, Slider, Dropdown / Select, List Item, Grid Item, Modal Dialog, Confirmation Dialog, Toast / Notification, Tooltip, Progress Bar, Input Field, Tab Bar, Scroll Container.
|
||||
|
||||
## Standard Control Patterns
|
||||
|
||||
---
|
||||
|
||||
#### Button (Primary)
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: The single most important action on a screen. "Start Game,"
|
||||
"Confirm," "Accept," "Buy." There should be at most one Primary button visible
|
||||
at a time. It is the answer to "what does the player most likely want to do here?"
|
||||
**When NOT to Use**: Alternative or secondary actions; destructive actions that
|
||||
require confirmation before the consequence is irreversible; any action that is
|
||||
not the primary intent of the screen.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Full-opacity fill, primary color from art-bible. Label centered. | — | — | — | — |
|
||||
| Hovered (mouse) | Brightness +15%, subtle scale 1.03x, cursor changes to pointer | Mouse over element | Transition from Default | 80ms ease-out | [UI hover sound — see Sound Standards] |
|
||||
| Focused (keyboard/gamepad) | Focus ring visible (2px, offset 3px, high contrast color). Same brightness as Hovered. | Tab / D-pad navigation | Transition from Default | 80ms ease-out | [UI focus sound — same as hover] |
|
||||
| Pressed | Scale 0.97x, brightness -10% | Click / Enter / A (Xbox) / Cross (PS) | Action fires on press-up, not press-down. Scale on press-down. | 60ms ease-in for press; 80ms ease-out on release | [UI confirm sound] |
|
||||
| Disabled | 40% opacity, no pointer cursor, no hover state | — | No response | — | — |
|
||||
| Loading (post-press) | Replace label with spinner. Button remains at pressed scale, disabled state. | — | Prevents double-submission | Duration of async operation | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard: Tab to focus, Enter or Space to activate. Must be reachable from any other interactive element on screen via Tab sequence.
|
||||
- Gamepad: D-pad or left stick to navigate focus to button. A (Xbox) / Cross (PS) to activate. Focus must be placed on Primary button by default when screen opens.
|
||||
- Screen reader: Button must expose accessible name matching visible label. Role: "button." State: "dimmed" when disabled. Activation announcement: "[Label] button — [result of action, if known]."
|
||||
- Colorblind: Do not rely on color alone to distinguish Primary from Secondary. Primary uses higher visual weight (fill vs. outline, or larger size) in addition to color differentiation.
|
||||
- Minimum touch target: 44x44pt (iOS HIG) / 48x48dp (Android). Apply even on PC if touch support is possible.
|
||||
|
||||
**Implementation Notes**:
|
||||
[Godot: Extend `Button` control. Override `_draw()` for custom states rather than
|
||||
modifying themes mid-state. Use `focus_mode = FOCUS_ALL` to ensure keyboard
|
||||
focusability. Set `mouse_default_cursor_shape = CURSOR_POINTING_HAND`. For the
|
||||
scale animation, use a Tween on the `scale` property of the button's parent
|
||||
Control — scaling the Button itself can clip children.]
|
||||
|
||||
---
|
||||
|
||||
#### Button (Secondary)
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Alternative or cancel action. "Back," "Cancel," "Skip," "Maybe
|
||||
Later." Lower visual weight than Primary — it should recede visually, not compete.
|
||||
**When NOT to Use**: Destructive actions (use Button (Destructive)). The most
|
||||
important action on the screen (use Button (Primary)).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Outlined style (border only, transparent fill), secondary color. Slightly smaller or lower weight than Primary. | — | — | — | — |
|
||||
| Hovered | Background fill appears at 15% opacity. Border brightens. Scale 1.02x. | Mouse over | Transition from Default | 80ms ease-out | [UI hover sound — softer variant than Primary] |
|
||||
| Focused | Focus ring, same specification as Primary. | Tab / D-pad | Transition from Default | 80ms ease-out | [UI focus sound] |
|
||||
| Pressed | Scale 0.97x, fill opacity increases to 30% | Click / Enter / B (Xbox) / Circle (PS) on focused state | Action fires on press-up | 60ms ease-in | [UI cancel/back sound] |
|
||||
| Disabled | 40% opacity | — | No response | — | — |
|
||||
|
||||
**Accessibility**: Same requirements as Button (Primary). Accessible name must
|
||||
match visible label. In a dialog with Primary and Secondary buttons, the Secondary
|
||||
button typically maps to the platform "cancel" input (B / Circle / Escape) as well
|
||||
as direct focus activation.
|
||||
|
||||
**Implementation Notes**: [Same as Button (Primary). Where a Primary and Secondary
|
||||
appear together, ensure Secondary is always positioned consistently — right/bottom
|
||||
of Primary on horizontal layouts, or below Primary on vertical layouts. Consistency
|
||||
across screens is more important than per-screen aesthetic preference.]
|
||||
|
||||
---
|
||||
|
||||
#### Button (Destructive)
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Any action that is irreversible and causes loss of player data or
|
||||
significant progress: "Delete Save File," "Reset All Settings," "Leave Match,"
|
||||
"Discard Changes." The visual treatment signals danger before the player presses.
|
||||
**When NOT to Use**: Actions that can be undone, or actions that are merely
|
||||
consequential but reversible.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Outlined or filled with destructive color (typically a desaturated red — confirm colorblind compatibility in accessibility-requirements). Label may include a warning icon. | — | — | — | — |
|
||||
| Hovered / Focused | Same behavior as Button (Primary) hover/focus but with destructive color | — | — | 80ms | [UI hover sound] |
|
||||
| Pressed (first press) | Does NOT execute the action. Instead, opens Confirmation Dialog pattern (see below). The button itself shows a brief pulse animation. | Click / Enter | Trigger Confirmation Dialog | 100ms pulse | [UI warning sound — distinct from standard confirm] |
|
||||
| — | Confirmation Dialog handles the actual execution | — | — | — | — |
|
||||
| Disabled | 40% opacity | — | No response | — | — |
|
||||
|
||||
> **Critical rule**: A Button (Destructive) NEVER executes its action directly.
|
||||
> It always triggers a Confirmation Dialog. There are no exceptions. A player
|
||||
> who presses it by accident must always have one more opportunity to back out.
|
||||
> Games that skip confirmation on destructive actions generate the most visible
|
||||
> negative community sentiment of any UX failure type. See: every "accidentally
|
||||
> deleted save file" complaint on any game forum.
|
||||
|
||||
**Accessibility**: Screen reader must announce the destructive nature: "[Label] button — this action cannot be undone." In addition to accessible name, use the `description` property if available to add the warning text.
|
||||
|
||||
**Implementation Notes**: [Destructive button triggers a separate Confirmation Dialog scene. Pass the action callback to the dialog — the button itself does not hold the execution logic. This separation prevents accidental execution if the confirmation dialog has a bug.]
|
||||
|
||||
---
|
||||
|
||||
#### Toggle
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Binary on/off settings where both states are equally valid and
|
||||
the current state must be visible at a glance. "Subtitles: On/Off," "Aim Assist:
|
||||
On/Off," "Notifications: On/Off."
|
||||
**When NOT to Use**: Selections from more than two options (use Dropdown). Actions
|
||||
that happen once rather than representing a persistent state (use Button). Cases
|
||||
where the consequence of toggling is complex enough to need explanation (show
|
||||
a description field alongside).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Off / Default | Track: muted fill. Thumb: leftmost position. Label: "Off" or state label. | — | — | — | — |
|
||||
| Hovered | Track brightens 10%. Cursor: pointer. | Mouse over | Transition | 60ms | [UI hover sound] |
|
||||
| Focused | Focus ring around entire toggle element (track + thumb). | Tab / D-pad | — | 60ms | [UI focus sound] |
|
||||
| Pressed / Activated | Thumb slides to right side. Track fill changes to active color. Label changes to "On" or active state label. State persists. | Click / Enter / A / Cross | Toggle state change. Fire onChange event. Persist value. | 150ms ease-in-out for slide | [Toggle ON sound] |
|
||||
| Pressed / Deactivated | Thumb slides to left. Track reverts to muted fill. | Same inputs | Toggle state change | 150ms ease-in-out | [Toggle OFF sound — subtly different from ON] |
|
||||
| Disabled | 40% opacity. No interaction. Current state still visible. | — | No response | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard/Gamepad: Space or Enter to toggle. Avoid requiring directional inputs (left/right) to toggle — some users cannot predict that behavior.
|
||||
- Screen reader: Role: "switch." State: "on" or "off" — the accessible name should NOT include the state (the screen reader announces state separately). Correct: accessible name "Subtitles," state "on." Incorrect: accessible name "Subtitles On."
|
||||
- The toggle label (not just the visual thumb position) must change to show current state for players who cannot reliably distinguish left from right positions.
|
||||
|
||||
**Implementation Notes**: [Godot: Use a custom Control or a CheckButton. The
|
||||
built-in CheckButton provides accessibility role but uses a checkbox-style visual;
|
||||
a custom slide-toggle animation may be needed for the target art style. Ensure
|
||||
the slide animation is skipped when motion reduction mode is active — in that
|
||||
case, snap to final state instantly.]
|
||||
|
||||
---
|
||||
|
||||
#### Slider
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Selecting a value from a continuous range where approximate values
|
||||
are acceptable and the range and relative position matter. Volume (0–100%), brightness,
|
||||
text size. The visual representation of position is itself useful information.
|
||||
**When NOT to Use**: Precise value entry (use Input Field). Selection from a short
|
||||
discrete list (use Dropdown). Binary state (use Toggle).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Track (full width). Fill (left of thumb, shows current value). Thumb (draggable handle). Current value label (right of track or above thumb). | — | — | — | — |
|
||||
| Hovered | Thumb enlarges slightly (1.2x). Track brightens. | Mouse over | — | 60ms | — |
|
||||
| Focused | Focus ring on thumb. Track brightens. | Tab / D-pad | — | 60ms | [UI focus sound] |
|
||||
| Dragging (mouse) | Thumb follows cursor. Fill updates in real time. Value label updates in real time. | Click + drag on thumb | Continuous value update. Fire onChange continuously. | Real time | [Slider adjust sound — subtle, loops while dragging] |
|
||||
| Keyboard / D-pad adjust | Thumb moves one step (5% of range per press, or 1 discrete unit). | Left/Right arrows or Left/Right D-pad while focused | Step value change. Fire onChange per step. | Instant | [Slider step sound — one click per step] |
|
||||
| Keyboard fast adjust | Larger step (25% of range). | Page Up / Page Down while focused | Large step value change | Instant | [Same step sound] |
|
||||
| Released | Value locks. onChange fires final value. | Mouse release | — | — | — |
|
||||
| Disabled | 40% opacity. No interaction. Value visible. | — | No response | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard: Left/Right arrows to adjust by small step. Page Up/Page Down for large step. Home/End to jump to min/max.
|
||||
- Screen reader: Role: "slider." Accessible name: the label (e.g., "Music Volume"). Current value announced on every change: "Music Volume, 80 percent." Min/max values announced on first focus.
|
||||
- All sliders must show a numeric value alongside the visual position. Relying only on track fill position excludes players who cannot perceive relative position.
|
||||
|
||||
**Implementation Notes**: [Godot `HSlider`: set `step` to appropriate increment.
|
||||
Override keyboard input to add Page Up/Down support via `_input()`. Bind the
|
||||
`value_changed` signal to update the displayed numeric label. When motion reduction
|
||||
mode is enabled, ensure value label updates are the sole feedback — do not suppress
|
||||
them. Rumble feedback on gamepad slider adjustment is a nice enhancement for
|
||||
accessibility.]
|
||||
|
||||
---
|
||||
|
||||
#### Dropdown / Select
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Selection from a discrete list of 3-15 options where only the
|
||||
selected value needs to be visible at rest. Display resolution, language, window
|
||||
mode, input preset. The closed state shows only the current selection.
|
||||
**When NOT to Use**: Binary choices (use Toggle). More than ~15 options (use a
|
||||
full List pattern or a scrollable Select). When comparing options matters as much
|
||||
as selecting one (show options visibly, e.g., as a horizontal selector or list).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Closed / Default | Label (left). Current value (right). Chevron-down icon (far right). | — | — | — | — |
|
||||
| Hovered | Row background fills at 10% opacity | Mouse over | — | 60ms | — |
|
||||
| Focused (closed) | Focus ring on entire row. | Tab / D-pad | — | 60ms | [UI focus sound] |
|
||||
| Opening | Dropdown list appears below (or above if near screen bottom). List items visible. Previously selected item highlighted. Focus moves to selected item inside list. | Click / Enter / A / Cross | Open list | 100ms ease-out (expand) | [UI expand sound] |
|
||||
| List item hovered/focused | List item highlights | Mouse / D-pad | — | 60ms | [UI hover sound] |
|
||||
| List item selected | List closes. Closed state shows new value. onChange event fires. | Click / Enter / A / Cross on item | Select value, close list | 80ms ease-in (collapse) | [UI confirm sound] |
|
||||
| Dismissed without selecting | List closes. Value unchanged. | Escape / B / Circle / click outside | Dismiss | 80ms | [UI cancel sound] |
|
||||
| Disabled | 40% opacity. No interaction. | — | — | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard: Up/Down arrows navigate list items while open. Enter selects. Escape dismisses. First letter of an option jumps focus to first matching item.
|
||||
- Screen reader: Role: "combobox." Accessible name: the field label. Expanded/collapsed state announced. Current value announced when focused. Each list item announces its value and position: "English, 1 of 12."
|
||||
- The dropdown list must never obscure the current item or the control that opened it — this is a common failure on small screens.
|
||||
|
||||
**Implementation Notes**: [Godot: Custom implementation using a `Button` (the
|
||||
closed state) and a `PopupMenu` or a `VBoxContainer` revealed by animation. Native
|
||||
`OptionButton` provides accessibility but limited visual customization. Ensure
|
||||
the popup positions itself above the control if it would be clipped by the screen
|
||||
bottom. Close the popup on `_input` detecting click outside its rect.]
|
||||
|
||||
---
|
||||
|
||||
#### List Item
|
||||
|
||||
**Category**: Layout / Input
|
||||
**Status**: Draft
|
||||
**When to Use**: A single selectable row in a vertically scrollable list. Achievements,
|
||||
quest log entries, settings categories, save file slots. The list is the container;
|
||||
this is the row within it.
|
||||
**When NOT to Use**: Grid layouts where items exist in two dimensions (use Grid Item).
|
||||
Non-selectable content rows (remove hover/focus states and the pressed state).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Full-width row. Icon (optional, left). Primary label. Secondary label / metadata (right or below primary). Chevron (right, if navigates deeper). | — | — | — | — |
|
||||
| Hovered | Row background at 12% opacity highlight. | Mouse over | — | 60ms | — |
|
||||
| Focused | Focus ring on row OR row background at 20% opacity (consistent with platform convention). | D-pad / Tab | — | 60ms | [UI focus sound] |
|
||||
| Selected (persistent) | Row background at 25% opacity. May show a selection indicator (left border, checkmark). Distinct from focused state — a row can be selected but not focused. | — | Rendered state | — | — |
|
||||
| Pressed / Activated | Brief brightness flash, then navigates or performs action | Click / Enter / A / Cross | Navigation or action | 80ms flash | [UI confirm sound] |
|
||||
| Disabled | 40% opacity. No interaction. | — | — | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard/Gamepad: Up/Down arrows or D-pad to move between list items. The list must handle focus cycling — reaching the bottom should stop (not wrap) unless wrapping is explicitly designed.
|
||||
- Screen reader: Role: "listitem." Parent list role: "list." Accessible name: primary label content. Metadata (secondary label) is optionally included in the description. Position announced: "Quest Log, 3 of 12."
|
||||
- Minimum row height: 44pt / 48dp for touch. For controller-primary platforms, 56px rows are more comfortable.
|
||||
|
||||
**Implementation Notes**: [Godot: Use a `VBoxContainer` inside a `ScrollContainer`.
|
||||
Each row is a custom `Control` or `PanelContainer` with a `_gui_input` override.
|
||||
For keyboard navigation inside the scroll container, implement custom focus
|
||||
traversal — Godot's default Tab navigation does not scroll the container to keep
|
||||
focused items in view. Use `ensure_control_visible()` on the scroll container.]
|
||||
|
||||
---
|
||||
|
||||
#### Grid Item
|
||||
|
||||
**Category**: Layout / Input
|
||||
**Status**: Draft
|
||||
**When to Use**: A selectable cell in a two-dimensional grid. Inventory slots,
|
||||
ability select, crafting ingredient selection, character portrait selection. The
|
||||
grid is the container; this is the cell.
|
||||
**When NOT to Use**: Single-column content (use List Item). Non-selectable display
|
||||
cells (remove interactive states).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Empty | Empty slot visual (subtle border or dashed outline). Different from disabled. | — | — | — | — |
|
||||
| Populated | Item icon fills cell. Stack count (bottom right, if applicable). Quality indicator (border color or icon overlay). | — | — | — | — |
|
||||
| Hovered | Brightness +15%. Tooltip appears after 400ms delay. | Mouse over | — | 60ms | — |
|
||||
| Focused | Focus ring (2px, offset 2px). Same brightness as hovered. Tooltip appears after 400ms delay or immediately on gamepad. | D-pad navigation | — | 60ms | [UI focus sound] |
|
||||
| Selected (persistent) | Distinct border (thicker, contrasting color). May show selection checkmark. | Click / Enter / A / Cross | Select item. Can coexist with focused state on a different cell. | Instant | [UI select sound] |
|
||||
| Pressed | Brief scale 0.95x, then executes action | Double-click / Enter / A / Cross | Action (equip, use, inspect — defined by context) | 80ms | [UI confirm sound] |
|
||||
| Locked | Padlock overlay icon on populated content. No hover/focus states. | — | No interaction | — | — |
|
||||
| Drag source | Cell dims (50% opacity), drag preview appears at cursor. | Click + drag (mouse only) | Begin drag operation | Instant | [UI grab sound] |
|
||||
| Drop target (valid) | Cell brightens, accepting color indicator | Item dragged over | — | 60ms | — |
|
||||
| Drop target (invalid) | Red tint or shake animation | Item dragged over invalid slot | — | 60ms | [UI error sound] |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard/Gamepad: D-pad or arrow keys navigate cells. The grid must communicate its dimensions to screen readers. Row/column position announced.
|
||||
- Screen reader: Role: "gridcell." Parent role: "grid." Accessible name: item name (or "empty slot" for empty cells). State: "selected" when selected, "dimmed" when locked. Position: "row 2, column 3."
|
||||
- Tooltips must be reachable by keyboard — they must appear when the cell is focused, not only when hovered.
|
||||
|
||||
**Implementation Notes**: [Godot: `GridContainer` with fixed column count. Each
|
||||
cell is a custom `Control`. Implement custom D-pad navigation by overriding
|
||||
`_gui_input` and calculating the cell to the left/right/above/below based on
|
||||
index and column count. `GridContainer` does not provide this natively.]
|
||||
|
||||
---
|
||||
|
||||
#### Modal Dialog
|
||||
|
||||
**Category**: Feedback / Layout
|
||||
**Status**: Draft
|
||||
**When to Use**: A decision or acknowledgment that must be resolved before the
|
||||
player can continue. The dialog is blocking — background content is dimmed and
|
||||
non-interactive. "Are you sure?", "Your progress will be saved.", error states.
|
||||
**When NOT to Use**: Non-blocking notifications (use Toast / Notification). Information
|
||||
that can wait until the player is ready (add it to a persistent help system instead).
|
||||
Dialogs that should allow the player to continue playing behind them.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Opening | Background overlay animates from 0 to 60% opacity. Dialog panel scales from 0.9 to 1.0. Dialog enters from center (not from an edge). | Triggered by code | Focus moves to first interactive element in dialog (or the Primary button) | 200ms ease-out | [UI modal open sound] |
|
||||
| Active | Background non-interactive. Dialog has all input focus. Player cannot interact with background. | Keyboard / gamepad navigates within dialog only | — | — | — |
|
||||
| Dismissing (confirmed) | Dialog panel scales to 1.1 then fades. Overlay fades to 0%. | Primary button pressed | Execute action, return focus to trigger element | 180ms | [UI confirm sound] |
|
||||
| Dismissing (cancelled) | Dialog panel scales to 0.9 then fades. Overlay fades to 0%. | Secondary button / Escape / B / Circle | No action, return focus to trigger element | 150ms | [UI cancel sound] |
|
||||
| Cannot dismiss | If the dialog represents a blocking error, do not provide a cancel path. Provide only resolution options. | — | — | — | — |
|
||||
|
||||
> **Focus trap rule**: While a modal dialog is open, Tab and D-pad navigation
|
||||
> must cycle within the dialog's interactive elements only. It must not be possible
|
||||
> to navigate focus outside the dialog to the background content. This is both
|
||||
> an accessibility requirement (WCAG 2.1 SC 2.1.2) and a UX integrity requirement.
|
||||
> When the dialog closes, focus must return to the element that triggered it,
|
||||
> not to the top of the page.
|
||||
|
||||
**Accessibility**:
|
||||
- Screen reader: Dialog container role: "dialog." Accessible name: dialog title (required — every dialog must have a title, even if visually hidden). On open, screen reader announces dialog title and first focusable element. Focus trap active.
|
||||
- Keyboard: Escape key always maps to the cancel/dismiss action (same as Secondary button or close button). Enter always maps to the primary/confirm action.
|
||||
- Motion reduction: Scale animation replaced with instant appear/disappear. Overlay fade retained at 100ms (faster).
|
||||
|
||||
**Implementation Notes**: [Godot: Implement as a `CanvasLayer` with a high layer
|
||||
value (100+) to ensure it renders above all game content. The background overlay
|
||||
is a full-screen `ColorRect` at 60% black opacity. Use `grab_focus()` on the
|
||||
dialog's primary button after the open animation completes. Override `_input()` to
|
||||
implement the focus trap — intercept Tab navigation and reroute to the dialog's
|
||||
focusable elements.]
|
||||
|
||||
---
|
||||
|
||||
#### Confirmation Dialog
|
||||
|
||||
**Category**: Feedback / Layout
|
||||
**Status**: Draft
|
||||
**When to Use**: The specific case of confirming a destructive action. Always
|
||||
triggered by Button (Destructive). Always has exactly two options: confirm (labeled
|
||||
with the specific action, not "OK") and cancel.
|
||||
**When NOT to Use**: Non-destructive confirmations. Errors or notifications that
|
||||
do not require a decision. Any dialog with more than two actions.
|
||||
|
||||
> **Label rule**: The confirm button must be labeled with the specific action,
|
||||
> not a generic "OK" or "Yes." "Delete Save File" not "OK." "Leave Match" not
|
||||
> "Yes." This reduces mistakes for players who have difficulty reading the dialog
|
||||
> content quickly. The pattern comes from Apple HIG and is validated by decades
|
||||
> of usability research.
|
||||
|
||||
**Structure**:
|
||||
- Title: Brief, action-describing. "Delete save file?" not "Are you sure?"
|
||||
- Body: One sentence stating the consequence. "This cannot be undone."
|
||||
- Confirm button: Button (Primary) — labeled with the specific action. "Delete Save File."
|
||||
- Cancel button: Button (Secondary) — "Cancel."
|
||||
- Default focus: Cancel (safer default — reduces accidental destructive actions).
|
||||
|
||||
**Accessibility**: Inherits all Modal Dialog accessibility. Additionally: screen
|
||||
reader announces "Alert dialog, [title]" to signal destructive context. Default
|
||||
focus on Cancel is a requirement, not a preference.
|
||||
|
||||
**Implementation Notes**: [Confirmation Dialog is a specific instance of Modal
|
||||
Dialog — implement it as a subclass or as a parameterized scene. The default
|
||||
focus on Cancel is critical: set `grab_focus()` on the Cancel button, not the
|
||||
Confirm button, after open animation completes.]
|
||||
|
||||
---
|
||||
|
||||
#### Toast / Notification
|
||||
|
||||
**Category**: Feedback
|
||||
**Status**: Draft
|
||||
**When to Use**: Brief, non-blocking information that does not require a player
|
||||
decision. "Game saved." "Achievement unlocked." "Your inventory is full." The player
|
||||
can continue playing; the notification disappears on its own.
|
||||
**When NOT to Use**: Information that requires a decision (use Modal Dialog).
|
||||
Errors that require the player to take action. Critical information that the player
|
||||
must not miss.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Entering | Slides in from screen edge (typically bottom-right, away from primary action areas). Fades from 0 to 100% opacity. | Triggered by code | — | 200ms ease-out | [Sound matching notification type — see Sound Standards] |
|
||||
| Displayed | Full opacity. Optional: icon (left), title, body text (optional), dismiss button (X, optional). | Pointer hover pauses auto-dismiss timer | Pause auto-dismiss | — | — |
|
||||
| Auto-dismiss | Fades from 100 to 0% opacity, slides out | Timer expires (5 seconds default for one-line; 8 seconds for two-line) | Remove from queue | 200ms ease-in | — |
|
||||
| Manual dismiss | Fades and slides out immediately | Click/tap X button or swipe on touch | Remove | 150ms | [UI cancel sound, quiet] |
|
||||
| Queue overflow | New notification pushes oldest out early | New notification triggered while previous is displayed | FIFO queue, max 3 simultaneous | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Screen reader: Toasts must be read aloud without requiring focus. In HTML, this uses `role="status"` or `role="alert"`. In game UI, this requires the engine's accessibility notification system. Verify engine support in engine-reference docs.
|
||||
- Motion reduction: Slide animation replaced with fade only.
|
||||
- Toasts must never be the sole communication channel for information the player needs to act on. If the information requires action, use a persistent UI element in addition to the toast.
|
||||
- Auto-dismiss timer: 5 seconds is the minimum. Players with cognitive processing differences may need more time. Consider a setting to extend to 10 or 15 seconds.
|
||||
|
||||
**Implementation Notes**: [Godot: Manage a queue of `PanelContainer` scenes in a
|
||||
`VBoxContainer` anchored to a screen corner. Each toast is instantiated, added to
|
||||
the container, then auto-removed after a timer. The container should be on a high
|
||||
`CanvasLayer` (50+) but below modal dialogs (100+). Animate using a `Tween` on
|
||||
`modulate.a` and `position.x`. When motion reduction is active, skip the position
|
||||
animation.]
|
||||
|
||||
---
|
||||
|
||||
#### Tooltip
|
||||
|
||||
**Category**: Feedback
|
||||
**Status**: Draft
|
||||
**When to Use**: Contextual information that supplements a visible label. Item
|
||||
descriptions in inventory. Stat explanations on a character sheet. Setting
|
||||
descriptions in accessibility options. The player must be able to access this
|
||||
information or proceed without it.
|
||||
**When NOT to Use**: Information the player MUST read to complete an action — put
|
||||
that in the label or body text, not a tooltip. Tooltips are not discoverable
|
||||
on mobile touch without a hover state. On touch-only platforms, use an info button
|
||||
that opens a description modal instead.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Hidden | — | — | — | — | — |
|
||||
| Hover trigger | — | Mouse enters element | Begin 400ms delay timer | — | — |
|
||||
| Gamepad/keyboard trigger | — | Element receives focus | Begin 300ms delay timer (shorter because navigation is intentional) | — | — |
|
||||
| Appearing | Tooltip panel fades in and scales from 0.95 to 1.0. Positioned near element (prefer above, adjust if near screen edge). | Timer expires | Show tooltip | 120ms ease-out | — |
|
||||
| Displayed | Tooltip visible. Title (optional). Body text. Max width: 300px. Multiple lines allowed. | — | — | — | — |
|
||||
| Hiding | Tooltip fades out | Mouse leaves element / focus moves away | Hide tooltip | 80ms ease-in | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Screen reader: Tooltip content must be accessible without hover. The accessible name of the parent element should include the most critical tooltip information. The full tooltip text is optionally in the `description` property. Screen reader reads tooltip content when element is focused.
|
||||
- The delay (300-400ms) prevents accidental tooltip display and is required — instant tooltips are disruptive in gamepad navigation.
|
||||
- Tooltip text must meet the same contrast requirements as body text (4.5:1 minimum).
|
||||
|
||||
**Implementation Notes**: [Godot: Attach a custom `TooltipControl` scene as a
|
||||
child of the trigger element. Show/hide with a `Timer` node. Position the tooltip
|
||||
using a `CanvasLayer` to ensure it appears above all other UI. For screen edges,
|
||||
detect if the tooltip rect extends beyond `get_viewport_rect()` and flip the
|
||||
position to the opposite side.]
|
||||
|
||||
---
|
||||
|
||||
#### Progress Bar
|
||||
|
||||
**Category**: Feedback / Layout
|
||||
**Status**: Draft
|
||||
**When to Use**: Linear progress toward a defined endpoint. Loading screens (time
|
||||
to completion), XP fill toward next level, quest objectives with countable progress
|
||||
("3 of 10 enemies defeated"), download progress.
|
||||
**When NOT to Use**: Circular or radial progress (use a separate Radial Progress
|
||||
pattern if needed). Values that fluctuate up and down rapidly (use Health/Resource
|
||||
Bar pattern). Values with no defined endpoint.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Track (full width, background color). Fill (left to right, value color). Value label (percentage or N/M, outside or inside fill). | — | — | — | — |
|
||||
| Value increasing | Fill width animates to new value | Value changes | Smooth fill animation | 300ms ease-out | [Context-dependent — XP gain has a sound; loading has none] |
|
||||
| Value at maximum | Fill reaches full width. Optional: completion animation (pulse, glow). | Value reaches 100% | Completion event fires | 200ms | [Completion sound if appropriate] |
|
||||
| Value at zero | Fill hidden (zero width). Track still visible. | — | — | — | — |
|
||||
| Indeterminate (unknown duration) | Animated loop (fill segment moves left-to-right, repeat). Used for loading of unknown duration. | — | — | Infinite loop | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Screen reader: Role: "progressbar." Accessible name: what is progressing (e.g., "Experience Points," "Loading"). Value: current numeric value AND percentage AND maximum. "Experience Points, 450 of 1000, 45 percent." Update on significant changes (not every pixel).
|
||||
- Do not rely only on fill color to communicate value. Include a numeric label.
|
||||
- Indeterminate progress bars: announce "Loading, in progress" — do not announce changes since the value is unknown.
|
||||
- Motion reduction: Indeterminate animation is replaced with a static "loading" indicator. Smooth fill animation is replaced with instant jump to new value.
|
||||
|
||||
**Implementation Notes**: [Godot: `ProgressBar` built-in with custom theming.
|
||||
For indeterminate mode, `ProgressBar` does not have a native indeterminate state
|
||||
in Godot 4.x — implement using a looping `Tween` on a fill element's position.
|
||||
Ensure the Tween is paused when motion reduction mode is active and a static
|
||||
indicator is shown instead.]
|
||||
|
||||
---
|
||||
|
||||
#### Input Field
|
||||
|
||||
**Category**: Input
|
||||
**Status**: Draft
|
||||
**When to Use**: Text entry. Player name on a new save, search within a list,
|
||||
remapping a key binding (special case — shows the key press, not typed text),
|
||||
entering a numeric value precisely.
|
||||
**When NOT to Use**: Selecting from known options (use Dropdown or List). On
|
||||
console-primary platforms, minimize text entry — it requires a virtual keyboard,
|
||||
which is high friction.
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default | Field border, placeholder text (label-style, muted color), empty input area. | — | — | — | — |
|
||||
| Hovered | Border brightens slightly | Mouse over | — | 60ms | — |
|
||||
| Focused | Border brightens fully. Cursor (blinking, 530ms on/530ms off). Placeholder text hidden. | Tab / click | Open virtual keyboard on console/mobile | Instant | [UI focus sound] |
|
||||
| Typing | Characters appear. Cursor advances. | Keyboard input | Update field value | Immediate | [Subtle keystroke sound, optional] |
|
||||
| Value present | Field shows typed value. Placeholder hidden. Clear button appears (X, right of field) if value is non-empty. | — | — | — | — |
|
||||
| Character limit reached | No further input accepted. Optional: brief shake animation and limit indicator changes color. | Input at limit | Reject further characters | 200ms shake | [UI error sound, subtle] |
|
||||
| Clear | Field empties. Cursor returns. Clear button disappears. | Click X / gamepad clear input | Clear value | Instant | [UI cancel sound, subtle] |
|
||||
| Validation error | Border turns error color (red — ensure colorblind safe). Error message appears below field. | On submit or on blur | Show error | Instant | [UI error sound] |
|
||||
| Validated / correct | Border turns success color (green — ensure colorblind safe). Success icon optional. | On validation pass | — | Instant | — |
|
||||
| Disabled | 40% opacity, no interaction. Value still visible. | — | — | — | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard: All standard text editing shortcuts (Home, End, Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+Z).
|
||||
- Screen reader: Role: "textbox." Accessible name: field label (not placeholder text). Current value announced. Character limit announced when reached. Validation errors announced immediately on occurrence.
|
||||
- Placeholder text must not be used as the only label — a visible label above or beside the field is required. Placeholder text disappears when the player types, causing confusion for players with cognitive or memory impairments.
|
||||
|
||||
**Implementation Notes**: [Godot `LineEdit`: set `placeholder_text` for the hint
|
||||
but always include a visible `Label` node as the field's accessible name. Bind
|
||||
`text_changed` signal for real-time validation. Bind `text_submitted` for form
|
||||
submission on Enter. On console, `LineEdit.call("_popup_keyboard")` or use the OS
|
||||
virtual keyboard API — verify against engine-reference/godot/ for Godot 4.6
|
||||
console keyboard API specifics.]
|
||||
|
||||
---
|
||||
|
||||
#### Tab Bar
|
||||
|
||||
**Category**: Navigation
|
||||
**Status**: Draft
|
||||
**When to Use**: Dividing a single screen's content into discrete sections where
|
||||
only one section is visible at a time. Character sheet tabs (Stats / Equipment /
|
||||
Skills), settings tabs (Gameplay / Graphics / Audio / Accessibility). Maximum
|
||||
5-6 tabs before the pattern breaks down and a sidebar navigation should be
|
||||
considered instead.
|
||||
**When NOT to Use**: More than 6 tabs. Content that benefits from simultaneous
|
||||
visibility (use a layout pattern instead). Navigation between different screens
|
||||
(use Screen Push).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Default (inactive tab) | Tab label. No active indicator. | — | — | — | — |
|
||||
| Active tab | Tab label. Active indicator (underline, fill, or contrasting background). Content area shows this tab's content. | — | — | — | — |
|
||||
| Hovered (inactive) | Tab background fills slightly | Mouse over | — | 60ms | — |
|
||||
| Focused (keyboard/gamepad) | Focus ring on tab label. | Tab key (within tab bar) or D-pad left/right on tab row | — | 60ms | [UI focus sound] |
|
||||
| Activated | Active indicator transitions to this tab. Content area transitions (fade or slide). | Click / Enter / A / Cross | Switch active tab. Content update. | 150ms ease | [UI tab switch sound] |
|
||||
| Gamepad shoulder button | — | L1/R1 (PS) or LB/RB (Xbox) | Switch to previous/next tab (standard platform convention) | 150ms | [UI tab switch sound] |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard: Arrow keys navigate between tabs within the tab bar (left/right). Tab key moves focus into the content area below. This follows the ARIA tab panel pattern.
|
||||
- Screen reader: Role: "tab" for individual tabs. Role: "tablist" for the container. Role: "tabpanel" for the content area. Active tab state: "selected." Accessible name: tab label. Tabpanel is labeled by its corresponding tab.
|
||||
- The active tab must be visually distinguishable by more than color alone (underline, fill pattern, or weight change in addition to color).
|
||||
|
||||
**Implementation Notes**: [Godot: `TabContainer` built-in. For custom visual
|
||||
styling, implement manually with a `HBoxContainer` of tab buttons and a
|
||||
`MarginContainer` for content. The shoulder button shortcut (LB/RB) must be
|
||||
implemented in the screen's `_input()` override — it is not built into Godot's
|
||||
tab system. Check platform conventions: Xbox uses LB/RB; PlayStation uses L1/R1;
|
||||
both are the same physical button, so a single binding works.]
|
||||
|
||||
---
|
||||
|
||||
#### Scroll Container
|
||||
|
||||
**Category**: Layout
|
||||
**Status**: Draft
|
||||
**When to Use**: Content that exceeds the visible area of its container. Inventory
|
||||
lists, lore entry text, credits, long settings lists. The scroll indicator shows
|
||||
the player that more content exists.
|
||||
**When NOT to Use**: Content that can be paginated instead (pagination may be
|
||||
clearer for dense list navigation). Infinite scroll (always provide a loading
|
||||
state and an end state).
|
||||
|
||||
**Interaction Specification**:
|
||||
|
||||
| State | Visual | Input | Response | Duration | Audio |
|
||||
|-------|--------|-------|----------|----------|-------|
|
||||
| Content fits | No scrollbar visible (or always-visible scrollbar at full height, depending on art direction). | — | — | — | — |
|
||||
| Scrollable | Scrollbar appears (right edge). Scrollbar thumb size represents viewport vs. content ratio. | — | — | — | — |
|
||||
| Scrolling (mouse) | Content moves. Scrollbar thumb moves proportionally. | Mouse wheel | Scroll by 3 lines per wheel tick (configurable in OS) | Smooth | — |
|
||||
| Scrollbar drag | Content moves. Thumb follows pointer. | Click + drag scrollbar thumb | Scroll proportionally | Real time | — |
|
||||
| Keyboard scroll | Content moves one item height per keypress. | Up/Down arrows when container is focused and no child is focused | Scroll by one unit | Immediate | — |
|
||||
| Gamepad scroll | Content moves to keep focused item in view. | D-pad navigation to items beyond visible area | Auto-scroll to keep focused item visible | Smooth 150ms | — |
|
||||
| Scroll top / bottom | Content stops. Scrollbar thumb at end. | Content boundary reached | Stop scrolling | — | — |
|
||||
| Focus follows scroll | When a child element receives focus, scroll container ensures it is fully visible. | Any child receives focus | Scroll to reveal focused element | 200ms ease | — |
|
||||
|
||||
**Accessibility**:
|
||||
- Keyboard/Gamepad: The scroll container itself should not require explicit scrollbar interaction — navigating list items inside it should auto-scroll to keep focused items in view.
|
||||
- Screen reader: The scroll container announces "scrollable" and the scroll position ("showing items 5 through 15 of 30"). This requires engine accessibility support — verify in engine-reference/godot/.
|
||||
- Fade edges (content fading at scroll boundaries to indicate more content exists) are a helpful visual affordance but must not be the only indicator that content exists beyond the visible area. Include a scrollbar.
|
||||
|
||||
**Implementation Notes**: [Godot `ScrollContainer`: call `ensure_control_visible()`
|
||||
on the focused child whenever `gui_focus_changed` fires inside the container.
|
||||
Bind this via a recursive `connect` on the container's `gui_focus_changed` signal.
|
||||
For smooth scroll animation, use a `Tween` on `scroll_vertical` rather than
|
||||
setting it directly.]
|
||||
|
||||
---
|
||||
@@ -0,0 +1,20 @@
|
||||
> Authoring guidance for interaction-pattern-library.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
# Interaction Pattern Library — Guidance Index
|
||||
|
||||
The guidance for this template is split by major section so consumers can load
|
||||
one part at a time. Read the file matching the section you are currently
|
||||
authoring — never all three at once.
|
||||
|
||||
| Template Section | Guidance File |
|
||||
|------------------|---------------|
|
||||
| Standard Control Patterns (Button variants, Toggle, Slider, Dropdown / Select, List Item, Grid Item, Modal Dialog, Confirmation Dialog, Toast / Notification, Tooltip, Progress Bar, Input Field, Tab Bar, Scroll Container) | `.claude/docs/templates/guidance/interaction-pattern-library-guide-standard-controls.md` |
|
||||
| Game-Specific UI Patterns (Inventory Slot, Ability / Skill Icon, Health / Resource Bar, Dialogue Box, Context Action Prompt, Damage Number) | `.claude/docs/templates/guidance/interaction-pattern-library-guide-game-specific.md` |
|
||||
| Navigation Patterns + Feedback and Loading Patterns (Screen Push / Pop / Replace, Focus Management, Escape / Cancel, Loading State, Empty State, Error State) | `.claude/docs/templates/guidance/interaction-pattern-library-guide-navigation-feedback.md` |
|
||||
|
||||
Each guidance file contains the full reference specification for its patterns —
|
||||
When to Use / When NOT to Use rationale, complete state tables with timing and
|
||||
audio values, accessibility requirements, and engine implementation notes. Use
|
||||
them as the worked-example source when filling the corresponding skeleton stubs
|
||||
in the template. The Pattern Catalog Index, Animation Standards, Sound
|
||||
Standards, and Open Questions sections remain in the template itself.
|
||||
+443
@@ -0,0 +1,443 @@
|
||||
> Authoring guidance for ux-spec.md. Load only the part covering the section currently being authored — not the whole file at once.
|
||||
|
||||
# UX Specification Template — Authoring Guidance
|
||||
|
||||
Guidance is organized by template section number. When authoring a section of a
|
||||
project's UX spec, read only that section's guidance below.
|
||||
|
||||
---
|
||||
|
||||
## Section 1 — Purpose & Player Need
|
||||
|
||||
> **Why this section exists**: Every screen must justify its existence from the
|
||||
> player's perspective. Screens that are designed from a developer perspective ("display
|
||||
> the save data") produce cluttered, confusing interfaces. Screens designed from the
|
||||
> player's perspective ("let the player feel confident their progress is safe before they
|
||||
> put the controller down") produce purposeful, calm interfaces. Write this section before
|
||||
> touching any layout decisions — it is the filter through which every subsequent choice
|
||||
> is evaluated.
|
||||
|
||||
**Authoring the player need**:
|
||||
|
||||
[One paragraph. Name the real human need, not the system function. Consider: what would
|
||||
a player say they want when they open this screen? What would frustrate them if it did
|
||||
not work? That frustration describes the need.
|
||||
|
||||
Example — bad: "Displays the player's current items and equipment."
|
||||
Example — good: "Lets the player understand what they're carrying and quickly decide what
|
||||
to take into the next encounter, without breaking their mental model of the game world.
|
||||
The inventory is the player's planning tool between moments of action."]
|
||||
|
||||
**Authoring the player goal**:
|
||||
|
||||
[One sentence. Specific enough that you could write an acceptance criterion for it.
|
||||
Example: "Find the item they are looking for within three button presses and equip it
|
||||
without navigating to a separate screen."]
|
||||
|
||||
**Authoring the game goal**:
|
||||
|
||||
[One sentence. This is what the system needs from this interaction. Example: "Record the
|
||||
player's equipment choices and relay them to the combat system before the next encounter
|
||||
loads." This section prevents UI that looks good but fails to serve the system it is
|
||||
part of.]
|
||||
|
||||
---
|
||||
|
||||
## Section 2 — Player Context on Arrival
|
||||
|
||||
> **Why this section exists**: Screens do not exist in isolation. A player opening the
|
||||
> inventory mid-combat is in a completely different cognitive and emotional state than
|
||||
> a player opening it after clearing a dungeon. The same information architecture can
|
||||
> feel oppressively complex in one context and trivially simple in another. Document the
|
||||
> context so that design decisions — what to show first, what to hide, what to animate,
|
||||
> what to simplify — are calibrated to the actual player arriving at this screen, not
|
||||
> an abstract user.
|
||||
|
||||
**Worked example answers for the context table**:
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| What was the player just doing? | [e.g., Completed a combat encounter / Pressed Esc from exploration / Triggered a story cutscene] |
|
||||
| What is their emotional state? | [e.g., High tension — just narrowly survived / Calm — exploring between objectives] |
|
||||
| What cognitive load are they carrying? | [e.g., High — actively tracking enemy positions / Low — no active threats] |
|
||||
| What information do they already have? | [e.g., They know they just picked up an item but haven't seen its stats yet] |
|
||||
| What are they most likely trying to do? | [e.g., Check if the new item is better than their current weapon — primary use case] |
|
||||
| What are they likely afraid of? | [e.g., Missing something, making an irreversible mistake, losing track of where they were] |
|
||||
|
||||
**Authoring the emotional design target**:
|
||||
|
||||
[One sentence describing the feeling the player should have while using this screen.
|
||||
Example: "Confident and in control — the player should feel like they have complete
|
||||
information and complete authority over their choices, with no ambiguity about outcomes."]
|
||||
|
||||
---
|
||||
|
||||
## Section 3 — Navigation Position
|
||||
|
||||
> **Why this section exists**: A screen that does not know where it sits in the
|
||||
> navigation hierarchy cannot define its entry/exit transitions, its back-button
|
||||
> behavior, or its relationship to the game's pause state. Navigation position also
|
||||
> reveals architectural problems early — if this screen is reachable from eight
|
||||
> different places, that is a complexity flag that should be resolved in design, not
|
||||
> implementation.
|
||||
|
||||
**Worked example — reachability table**:
|
||||
|
||||
| Entry Point | Triggered By | Notes |
|
||||
|-------------|-------------|-------|
|
||||
| [e.g., Main Menu → Play] | [Player selects "New Game"] | [Primary entry point] |
|
||||
| [e.g., Pause Menu → Resume] | [Player presses Start from any gameplay state] | [Secondary entry] |
|
||||
| [e.g., Game event] | [Tutorial system forces open first time only] | [Systemic entry — must not break if player dismisses] |
|
||||
|
||||
---
|
||||
|
||||
## Section 4 — Entry & Exit Points
|
||||
|
||||
> **Why this section exists**: Entry and exit define the screen's contract with the
|
||||
> rest of the navigation system. Every entry point must have a corresponding exit point.
|
||||
> Transitions that are undefined become bugs — the player finds themselves stuck, or the
|
||||
> game state becomes inconsistent. Fill this table completely before implementation
|
||||
> begins. Empty cells are a sign that design work is unfinished.
|
||||
|
||||
**Worked example — entry table**:
|
||||
|
||||
| Trigger | Source Screen / State | Transition Type | Data Passed In | Notes |
|
||||
|---------|----------------------|-----------------|----------------|-------|
|
||||
| [e.g., Player presses Inventory button] | [Gameplay / Exploration state] | [Overlay push — game pauses] | [Current player loadout, inventory contents] | [Works from any non-combat state] |
|
||||
| [e.g., Item pickup prompt accepted] | [Gameplay / Item Pickup dialog] | [Replace dialog with full inventory] | [Newly acquired item pre-highlighted] | [The new item should be visually distinguished on open] |
|
||||
| [e.g., Quest system directs player to inventory] | [Gameplay / Quest Update notification] | [Overlay push] | [Quest-relevant item ID for highlight] | [Screen should deep-link to the relevant item] |
|
||||
|
||||
**Worked example — exit table**:
|
||||
|
||||
| Exit Action | Destination | Transition Type | Data Returned / Saved | Notes |
|
||||
|-------------|------------|-----------------|----------------------|-------|
|
||||
| [e.g., Player closes inventory (Back/B/Esc)] | [Previous state — Exploration] | [Overlay pop — game resumes] | [Updated equipment loadout committed] | [Changes must be committed before transition begins] |
|
||||
| [e.g., Player selects "Equip" on item] | [Same screen, updated state] | [In-place state change] | [Loadout change event fired] | [No navigation, just a state refresh] |
|
||||
| [e.g., Player navigates to Map from inventory shortcut] | [Map Screen] | [Replace] | [No data] | [Inventory state is preserved if player returns] |
|
||||
|
||||
---
|
||||
|
||||
## Section 5 — Layout Specification
|
||||
|
||||
> **Why this section exists**: The layout specification is the handoff artifact between
|
||||
> UX design and UI programming. It does not need to be pixel-perfect — it needs to
|
||||
> communicate hierarchy (what is important), proximity (what belongs together), and
|
||||
> proportion (what is big vs. small). ASCII wireframes achieve this without requiring
|
||||
> design software. A programmer who reads this section should be able to build the
|
||||
> correct structure without guessing. An artist who reads it should know where
|
||||
> visual weight should be concentrated.
|
||||
>
|
||||
> Draw the layout at one standard resolution (e.g., 1920x1080). Note adaptations
|
||||
> for other resolutions separately.
|
||||
|
||||
**Worked example — wireframe (5.1)**:
|
||||
|
||||
```
|
||||
Example:
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ [← Back] INVENTORY [Options] │ ← HEADER ZONE
|
||||
├──────────────────────────────────────────────┤
|
||||
│ ┌──────────────┐ ┌─────────────────────────┐│
|
||||
│ │ CATEGORY NAV │ │ ITEM DETAIL PANEL ││ ← CONTENT ZONE
|
||||
│ │ ● Weapons │ │ Item Name ││
|
||||
│ │ Armor │ │ {item icon} ││
|
||||
│ │ Consumable│ │ Stats comparison ││
|
||||
│ │ Key Items │ │ Description text... ││
|
||||
│ ├──────────────┤ └─────────────────────────┘│
|
||||
│ │ ITEM GRID │ │
|
||||
│ │ {□}{□}{□}{□} │ │
|
||||
│ │ {□}{□}{□}{□} │ │
|
||||
│ │ ... │ │
|
||||
│ └──────────────┘ │
|
||||
├──────────────────────────────────────────────┤
|
||||
│ [Equip] [Drop] [Compare] [Close] │ ← ACTION BAR
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Worked example — zone definitions table (5.2)**:
|
||||
|
||||
| Zone Name | Description | Approximate Size | Scrollable? | Overflow Behavior |
|
||||
|-----------|-------------|-----------------|-------------|-------------------|
|
||||
| [e.g., Header Zone] | [Top bar: navigation, screen title, global actions] | [Full width, ~10% height] | [No] | [Truncate long screen names with ellipsis] |
|
||||
| [e.g., Category Nav] | [Left panel: item category tabs] | [~25% width, ~75% height] | [Yes — vertical if categories exceed panel] | [Scroll indicator appears at bottom of list] |
|
||||
| [e.g., Item Grid] | [Center: grid of item icons for selected category] | [~45% width, ~75% height] | [Yes — vertical] | [Page-based: 4x4 grid, next page on overflow] |
|
||||
| [e.g., Detail Panel] | [Right: stats and description for selected item] | [~30% width, ~75% height] | [Yes — vertical for long descriptions] | [Fade at bottom, scroll to reveal] |
|
||||
| [e.g., Action Bar] | [Bottom: context-sensitive actions for selected item] | [Full width, ~15% height] | [No] | [Actions collapse to icon-only below 4] |
|
||||
|
||||
**Worked example — component inventory table (5.3)**:
|
||||
|
||||
| Component Name | Type | Zone | Purpose | Required? | Reuses Existing Component? |
|
||||
|----------------|------|------|---------|-----------|---------------------------|
|
||||
| [e.g., Back Button] | [Button] | [Header] | [Returns to previous screen] | [Yes] | [Yes — standard NavButton component] |
|
||||
| [e.g., Screen Title Label] | [Text] | [Header] | [Displays "INVENTORY" or context name] | [Yes] | [Yes — ScreenTitle component] |
|
||||
| [e.g., Category Tab] | [Toggle Button] | [Category Nav] | [Filters item grid by category] | [Yes] | [No — new component needed] |
|
||||
| [e.g., Item Slot] | [Icon + Frame] | [Item Grid] | [Represents one inventory slot, empty or filled] | [Yes] | [No — new component] |
|
||||
| [e.g., Item Name Label] | [Text] | [Detail Panel] | [Shows selected item's name] | [Yes] | [Yes — BodyText component] |
|
||||
| [e.g., Stat Comparison Row] | [Compound — label + value + delta] | [Detail Panel] | [Shows stat value vs. currently equipped] | [Yes] | [No — new component] |
|
||||
| [e.g., Equip Button] | [Primary Button] | [Action Bar] | [Equips selected item in appropriate slot] | [Yes] | [Yes — PrimaryAction component] |
|
||||
| [e.g., Empty State Message] | [Text + Icon] | [Item Grid] | [Shown when category has no items] | [Yes] | [Yes — EmptyState component] |
|
||||
|
||||
**Worked example — primary focus element on open**: [e.g., The first item in the Item Grid — or, if deep-linked, the highlighted item. If the grid is empty, focus lands on the first Category Tab.]
|
||||
|
||||
---
|
||||
|
||||
## Section 6 — States & Variants
|
||||
|
||||
> **Why this section exists**: A screen is not a single picture — it is a set of
|
||||
> states, each of which must look correct and behave correctly. Screens that are
|
||||
> designed only in their "happy path" state ship with broken empty states, invisible
|
||||
> loading indicators, and crashes when data is missing. Document every state before
|
||||
> implementation. The states table is also the test matrix for QA.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| State Name | Trigger | What Changes Visually | What Changes Behaviorally | Notes |
|
||||
|------------|---------|----------------------|--------------------------|-------|
|
||||
| [Loading] | [Screen is opening, data not yet available] | [Item Grid shows skeleton/shimmer placeholders; Action Bar buttons disabled] | [No interactions possible except Close] | [Should not be visible >500ms under normal conditions; if it is, investigate data fetch performance] |
|
||||
| [Empty — no items in category] | [Player switches to a category with zero items] | [Item Grid replaced by EmptyState component: icon + "Nothing here yet."] | [Action Bar shows no item actions; Drop/Equip/Compare all hidden] | [Do not show disabled buttons — remove them. Disabled buttons with no tooltip are confusing.] |
|
||||
| [Populated — items present] | [Category has at least one item] | [Item Grid fills with item slots; first slot is auto-focused] | [All item actions available for selected item] | [Default and most common state] |
|
||||
| [Item Selected] | [Player navigates to an item slot] | [Detail Panel populates; selected slot has focus ring; Action Bar updates to item's valid actions] | [Equip/Drop/Compare enabled based on item type] | [Equip is disabled if item is already equipped — show a "Equipped" badge instead] |
|
||||
| [Confirmation Pending — Drop] | [Player selects Drop action] | [Confirmation dialog overlays the screen] | [All background interactions suspended until dialog resolves] | [Use a modal confirmation, not an inline toggle. Items cannot be recovered after dropping.] |
|
||||
| [Error — data load failed] | [Inventory data could not be retrieved] | [Item Grid shows error state: icon + "Couldn't load items." + Retry button] | [Only Retry and Close are available] | [Log the error; do not expose technical details to player] |
|
||||
| [Item Newly Acquired] | [Screen opened from item pickup deep-link] | [Newly acquired item has a visual "New" badge; Detail Panel pre-populated with that item] | [Same as Item Selected but with badge until player navigates away] | [Badge persists until the player manually navigates off that slot once] |
|
||||
|
||||
---
|
||||
|
||||
## Section 7 — Interaction Map
|
||||
|
||||
> **Why this section exists**: This section is the source of truth for what every
|
||||
> input does on this screen. It forces the designer to think through every input
|
||||
> method (mouse, keyboard, gamepad, touch) and every interactive state (hover, focus,
|
||||
> pressed, disabled). Gaps in this table are bugs waiting to happen. The
|
||||
> interaction map is also the input for the accessibility audit — if an action is
|
||||
> only reachable by mouse, it will fail the keyboard and gamepad columns.
|
||||
|
||||
**Worked example — navigation inputs (7.1)**:
|
||||
|
||||
| Input | Platform | Action | Visual Response | Audio Cue | Notes |
|
||||
|-------|----------|--------|-----------------|-----------|-------|
|
||||
| [Arrow keys / D-Pad] | [All] | [Move focus within active zone] | [Focus ring moves to adjacent element] | [Soft navigation tick] | [Wrap at edges within zone; do not cross zones with arrows alone] |
|
||||
| [Tab / R1] | [KB / Gamepad] | [Move focus to next zone (Category → Grid → Detail → Action Bar)] | [Focus ring jumps to first element in next zone] | [Distinct zone-change tone] | [Shift+Tab / L1 goes backward] |
|
||||
| [Mouse hover] | [PC] | [Show hover state on interactive elements] | [Highlight / underline / color shift] | [None] | [Hover does NOT move focus — only click does] |
|
||||
| [Mouse click] | [PC] | [Select and focus the clicked element] | [Pressed state flash, then selected/focused] | [Soft click] | [Right-click opens context menu if applicable; otherwise no-op] |
|
||||
| [Touch tap] | [Mobile] | [Select and activate in one gesture] | [Press ripple] | [Soft click] | [Treat tap as click + confirm for low-risk actions; require explicit confirm for destructive actions] |
|
||||
|
||||
**Worked example — action inputs (7.2)**:
|
||||
|
||||
| Input | Platform | Context (What must be focused) | Action | Response | Animation | Audio Cue | Notes |
|
||||
|-------|----------|-------------------------------|--------|----------|-----------|-----------|-------|
|
||||
| [Enter / A button / Left click] | [All] | [Item slot focused] | [Select item → populate Detail Panel] | [Detail panel slides in or updates in place] | [Panel fade/slide in, 120ms] | [Soft select tone] | [If item already selected: no-op] |
|
||||
| [Enter / A button] | [All] | [Equip button focused] | [Equip selected item] | [Button animates press; item badge updates to "Equipped"; previously equipped item loses badge] | [Badge swap, 80ms] | [Equip success sound] | [Fires EquipItem event to Inventory system] |
|
||||
| [Triangle / Y button / Right-click] | [All] | [Item slot focused] | [Open item context menu] | [Context menu appears adjacent to item slot] | [Popover, 80ms] | [Menu open sound] | [Context menu contains: Equip, Drop, Inspect, Compare] |
|
||||
| [Square / X button] | [Gamepad] | [Item slot focused] | [Quick-equip without opening detail] | [Equip animation plays inline on slot] | [Slot flash, 80ms] | [Equip success sound] | [Convenience shortcut; does not change screen state] |
|
||||
| [Esc / B button / Back] | [All] | [Any, screen level] | [Close screen and return to previous state] | [Screen exit transition plays] | [Slide out, 200ms] | [Back/close tone] | [Commits all changes before closing. No discard — inventory is not a draft.] |
|
||||
| [F / L2] | [KB / Gamepad] | [Any] | [Toggle filter panel] | [Sort/filter overlay opens] | [Slide in from right, 200ms] | [Panel open tone] | [If no items in category, filter is disabled] |
|
||||
|
||||
**Worked example — state-specific behaviors (7.3)**:
|
||||
|
||||
| State | Input Restriction | Reason |
|
||||
|-------|------------------|--------|
|
||||
| [Loading] | [All item and action inputs disabled] | [No data to act on; prevent race conditions] |
|
||||
| [Confirmation dialog open] | [Only Confirm and Cancel inputs active] | [Modal — background is locked] |
|
||||
| [Error state] | [Only Retry and Close active] | [No data available to navigate] |
|
||||
|
||||
---
|
||||
|
||||
## Section 8 — Data Requirements
|
||||
|
||||
> **Why this section exists**: The separation between UI and game state is the most
|
||||
> important architectural boundary in a game's UI system. UI reads data; it does not
|
||||
> own it. UI fires events; it does not write state directly. This section defines
|
||||
> exactly what data this screen needs to display, where it comes from, and how
|
||||
> frequently it updates. Filling this table before implementation prevents two
|
||||
> common failure modes: (1) UI developers reaching into systems they should not touch,
|
||||
> and (2) systems not knowing they need to expose data until a UI is half-built.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Data Element | Source System | Update Frequency | Who Owns It | Format | Null / Missing Handling |
|
||||
|--------------|--------------|-----------------|-------------|--------|------------------------|
|
||||
| [e.g., Item list] | [Inventory System] | [On screen open; on InventoryChanged event] | [InventorySystem] | [Array of ItemData structs: id, name, icon_path, category, stats, is_equipped] | [Empty array → show Empty State. Never null — system must return array.] |
|
||||
| [e.g., Equipped loadout] | [Equipment System] | [On screen open; on EquipmentChanged event] | [EquipmentSystem] | [Dict mapping slot_id → item_id] | [Unequipped slot has null value — UI shows empty slot icon] |
|
||||
| [e.g., Item stat comparisons] | [Stats System] | [On item selection change] | [StatsSystem] | [Dict mapping stat_name → {current, new, delta}] | [If no item selected, detail panel shows placeholder. Stats system must handle this gracefully.] |
|
||||
| [e.g., Player currency] | [Economy System] | [On screen open only — inventory does not show live currency] | [EconomySystem] | [Int — gold pieces] | [If currency system not active for this game mode, hide the currency row entirely] |
|
||||
| [e.g., Newly acquired item flag] | [Inventory System] | [On screen open] | [InventorySystem] | [Array of item_ids flagged as new] | [If empty array, no badges shown] |
|
||||
|
||||
---
|
||||
|
||||
## Section 9 — Events Fired
|
||||
|
||||
> **Why this section exists**: This is the other half of the UI/system boundary.
|
||||
> Where Section 8 defines what the UI reads, this section defines what the UI
|
||||
> communicates back to the game. Specifying events at design time prevents UI
|
||||
> programmers from writing game logic, and prevents game programmers from being
|
||||
> surprised by what the UI does. Every destructive or state-changing player action
|
||||
> must appear in this table.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Player Action | Event Fired | Payload | Receiver System | Notes |
|
||||
|---------------|-------------|---------|-----------------|-------|
|
||||
| [Player equips an item] | [EquipItemRequested] | [{item_id: string, target_slot: string}] | [Equipment System] | [Equipment System validates the action and fires EquipmentChanged if successful; UI listens for EquipmentChanged to update its display] |
|
||||
| [Player drops an item] | [DropItemRequested] | [{item_id: string, quantity: int}] | [Inventory System] | [Fires only after player confirms the drop dialog. Inventory System removes the item and fires InventoryChanged.] |
|
||||
| [Player opens item compare] | [ItemCompareOpened] | [{item_a_id: string, item_b_id: string}] | [Analytics System] | [No game-state change — analytics event only. Compare view is purely local UI state.] |
|
||||
| [Player closes screen] | [InventoryScreenClosed] | [{session_duration_ms: int}] | [Analytics System] | [Fires on every close regardless of reason. Used for engagement metrics.] |
|
||||
| [Player navigates between categories] | [InventoryCategoryChanged] | [{category: string}] | [Analytics System] | [Analytics only. No game state change.] |
|
||||
|
||||
---
|
||||
|
||||
## Section 10 — Transition & Animation
|
||||
|
||||
> **Why this section exists**: Transitions are not decoration — they communicate
|
||||
> hierarchy and causality. A screen that slides in from the right implies the
|
||||
> player has moved forward. A screen that fades implies a context break. Inconsistent
|
||||
> transitions make navigation feel broken even when it is technically correct.
|
||||
> This section ensures transitions are specified intentionally, not left to the
|
||||
> developer's discretion, and that accessibility settings (reduced motion) are
|
||||
> planned for from the start.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Transition | Trigger | Direction / Type | Duration (ms) | Easing | Interruptible? | Skipped by Reduced Motion? |
|
||||
|------------|---------|-----------------|--------------|--------|----------------|---------------------------|
|
||||
| [Screen enter] | [Screen pushed onto stack] | [Slide in from right] | [250] | [Ease out cubic] | [No — must complete before interaction is enabled] | [Yes — instant appear at 0ms] |
|
||||
| [Screen exit — Back] | [Player presses Back] | [Slide out to right] | [200] | [Ease in cubic] | [No] | [Yes — instant disappear] |
|
||||
| [Screen exit — Forward] | [Player navigates to child screen] | [Slide out to left] | [200] | [Ease in cubic] | [No] | [Yes — instant] |
|
||||
| [Detail panel update] | [Player selects a new item] | [Cross-fade content] | [120] | [Linear] | [Yes — if player navigates quickly, previous animation cancels] | [Yes — instant swap] |
|
||||
| [Loading → Populated] | [Data arrives after load] | [Skeleton shimmer fades out, content fades in] | [180] | [Ease out] | [No] | [Yes — instant reveal] |
|
||||
| [Action Bar button press] | [Player activates a button] | [Scale down 95% on press, return on release] | [60 down / 60 up] | [Ease out / ease in] | [Yes — if released early, returns to normal] | [No — this is tactile feedback, not decorative motion] |
|
||||
| [Confirmation dialog open] | [Player initiates destructive action] | [Background dims 60% opacity; dialog scales up from 95%] | [150] | [Ease out] | [No] | [Yes — instant appear, no scale] |
|
||||
| [New item badge appear] | [Screen opens with newly acquired item] | [Badge pops from 0% to 110% to 100% scale] | [200 total] | [Ease out back] | [No] | [Yes — instant appear at 100% scale] |
|
||||
|
||||
---
|
||||
|
||||
## Section 11 — Input Method Completeness Checklist
|
||||
|
||||
> **Why this section exists**: Input completeness is not optional — it is a
|
||||
> certification requirement for console platforms and a legal risk area for
|
||||
> accessibility laws in multiple markets. Fill this checklist before marking
|
||||
> the spec as Approved. Any unchecked item blocks implementation start.
|
||||
|
||||
---
|
||||
|
||||
## Section 12 — Screen-Level Accessibility Requirements
|
||||
|
||||
> **Why this section exists**: Accessibility requirements must be specified at design
|
||||
> time because retrofitting them is expensive and often architecturally impractical.
|
||||
> This section documents requirements specific to this screen. Project-wide standards
|
||||
> live in `design/accessibility-requirements.md` — consult it before filling this
|
||||
> section so you do not duplicate or contradict project-level commitments.
|
||||
|
||||
**Worked example — text contrast table**:
|
||||
|
||||
| Text Element | Background Context | Required Ratio | Current Ratio | Pass? |
|
||||
|--------------|-------------------|---------------|---------------|-------|
|
||||
| [e.g., Item name in Detail Panel] | [Dark panel background ~#1a1a1a] | [4.5:1 (WCAG AA normal text)] | [TBD — verify in implementation] | [ ] |
|
||||
| [e.g., Category tab label — inactive] | [Mid-grey tab background] | [4.5:1] | [TBD] | [ ] |
|
||||
| [e.g., Category tab label — active] | [Accent color background] | [4.5:1] | [TBD] | [ ] |
|
||||
| [e.g., Action button label] | [Button color (varies by state)] | [4.5:1] | [TBD] | [ ] |
|
||||
| [e.g., Stat comparison delta (positive)] | [Detail panel] | [4.5:1 — do NOT rely on green color alone] | [TBD] | [ ] |
|
||||
|
||||
**Worked example — colorblind mitigations table**:
|
||||
|
||||
| Element | Colorblind Risk | Mitigation |
|
||||
|---------|----------------|------------|
|
||||
| [e.g., Stat delta indicators (red/green for worse/better)] | [Red-green colorblindness (Deuteranopia) — most common form] | [Add arrow icons (↑ / ↓) and +/- prefix in addition to color. Color is a redundant, not sole, indicator.] |
|
||||
| [e.g., Item rarity color coding (grey/green/blue/purple/orange)] | [Multiple types — rarity color is a common industry failure] | [Add rarity name text label below icon. Color is supplemental only.] |
|
||||
|
||||
**Worked example — focus order**:
|
||||
|
||||
[e.g.,
|
||||
1. Back button (Header)
|
||||
2. Options button (Header)
|
||||
3. Category Tab 1 — Weapons
|
||||
4. Category Tab 2 — Armor
|
||||
5. Category Tab 3 — Consumables
|
||||
6. Category Tab 4 — Key Items
|
||||
7. Item Slot [0,0]
|
||||
8. Item Slot [0,1] ... (grid traverses left-to-right, top-to-bottom)
|
||||
9. Last item slot
|
||||
10. Equip button (Action Bar)
|
||||
11. Drop button (Action Bar)
|
||||
12. Compare button (Action Bar)
|
||||
13. Close button (Action Bar)
|
||||
→ Cycles back to Back button
|
||||
|
||||
Focus does not enter the Detail Panel — it is a display panel driven by item focus, not independently navigable.]
|
||||
|
||||
**Worked example — screen reader announcements table**:
|
||||
|
||||
| State Change | Announcement Text | Announcement Timing |
|
||||
|--------------|------------------|---------------------|
|
||||
| [Screen opens] | ["Inventory screen. [N] items. [Active category] selected."] | [On screen focus settle] |
|
||||
| [Player focuses an item slot] | ["[Item name]. [Category]. [Rarity]. [Key stats summary]. [Equipped / Not equipped]."] | [On focus arrival] |
|
||||
| [Player equips an item] | ["[Item name] equipped to [slot name]."] | [After EquipmentChanged event confirmed] |
|
||||
| [Player drops an item] | ["[Item name] dropped."] | [After InventoryChanged event confirmed] |
|
||||
| [Category changes] | ["[Category name]. [N] items."] | [On category tab focus] |
|
||||
| [Empty state shown] | ["No items in [category name]."] | [When empty state renders] |
|
||||
|
||||
**Authoring the cognitive load assessment**:
|
||||
|
||||
[Estimate the number of information streams the player is simultaneously tracking while
|
||||
using this screen. For this screen: (1) item grid position, (2) item detail stats,
|
||||
(3) current equipment loadout for comparison, (4) available actions, (5) item category.
|
||||
That is 5 concurrent streams — within the standard 7±2 limit, but at the higher end.
|
||||
Mitigation: detail panel auto-updates on navigation so the player never needs to
|
||||
manually retrieve item info. Reduce active decisions by surfacing stat comparison
|
||||
automatically.]
|
||||
|
||||
---
|
||||
|
||||
## Section 13 — Localization Considerations
|
||||
|
||||
> **Why this section exists**: UI built without localization in mind breaks on first
|
||||
> translation. German text is typically 30–40% longer than English. Arabic and Hebrew
|
||||
> require right-to-left layout mirroring. Japanese and Chinese text may be significantly
|
||||
> shorter than English, creating awkward whitespace. These issues are cheap to plan for
|
||||
> and expensive to fix after a layout is built and shipped. Every text element should
|
||||
> have an explicit max-character count and a plan for overflow.
|
||||
|
||||
**Worked example table**:
|
||||
|
||||
| Text Element | English Baseline Length | Max Characters | Expansion Budget | RTL Behavior | Overflow Behavior | Risk |
|
||||
|--------------|------------------------|----------------|-----------------|--------------|-------------------|------|
|
||||
| [e.g., Screen title "INVENTORY"] | [9 chars] | [16 chars] | [78%] | [Mirror to right, or center — acceptable] | [Truncate with ellipsis — title is not critical content] | [Low] |
|
||||
| [e.g., Item name] | [~15 chars avg, max ~35 "Enchanted Dragon Scale Gauntlets"] | [50 chars] | [43%] | [Right-align in RTL layouts] | [Truncate with tooltip showing full name on hover/focus] | [Medium — long fantasy item names are common] |
|
||||
| [e.g., Item description] | [~80–120 chars] | [200 chars] | [67%] | [Right-align, wrap normally] | [Scroll within Detail Panel — no truncation] | [Low — panel is scrollable] |
|
||||
| [e.g., Action button "Equip"] | [5 chars] | [14 chars] | [180%] | [Button layout mirrors; text right-aligns] | [Shrink font to 90% minimum, then truncate] | [Medium — "Ausrüsten" in German is 9 chars] |
|
||||
| [e.g., Category tab "Consumables"] | [11 chars] | [18 chars] | [64%] | [Mirror tab position] | [Abbreviate: "Consum." — define abbreviations per language in loc file] | [High — long localized tab labels are a known problem] |
|
||||
|
||||
---
|
||||
|
||||
## Section 14 — Acceptance Criteria
|
||||
|
||||
> **Why this section exists**: Acceptance criteria are the contractual definition of
|
||||
> "done." Without them, implementation is complete when the developer says it is.
|
||||
> With them, implementation is complete when a QA tester can verify every item on
|
||||
> this list. Write criteria that a tester can verify independently, without asking the
|
||||
> designer what they meant. Every criterion should be binary — pass or fail, not
|
||||
> subjective.
|
||||
|
||||
**Worked example criteria (inventory screen)** — note how each is screen-specific
|
||||
and independently verifiable:
|
||||
|
||||
- [ ] Navigation between items produces no perceptible frame drop (maintain target framerate ±5fps)
|
||||
- [ ] All states (Loading, Empty, Populated, Error, Confirmation) render correctly
|
||||
- [ ] Item grid scrolls smoothly without frame drops when all item slots are populated
|
||||
- [ ] Inventory changes persist correctly after screen is closed and reopened
|
||||
- [ ] Screen handles InventoryChanged events fired by other systems while it is open without crashing
|
||||
- [ ] Stat comparison does not rely on color alone as the sole differentiator
|
||||
- [ ] Screen reader announces item name and key stats on focus (verify with platform screen reader)
|
||||
|
||||
---
|
||||
|
||||
## Section 15 — Open Questions
|
||||
|
||||
**Worked example questions**:
|
||||
|
||||
| Question | Owner | Deadline | Resolution |
|
||||
|----------|-------|----------|-----------|
|
||||
| [e.g., Should item comparison be automatic (always showing equipped stats) or player-triggered (press Compare)?] | [ui-designer] | [Sprint 4, Day 3] | [Pending] |
|
||||
| [e.g., Do we support controller cursor (free aim) in the item grid, or d-pad-only grid navigation?] | [lead-programmer + ui-designer] | [Sprint 4, Day 3] | [Pending — depends on ADR-0015 input model decision] |
|
||||
| [e.g., What is the game's item drop policy — permanent loss or drop-to-world?] | [systems-designer] | [Requires GDD update] | [Blocked on inventory GDD Edge Cases section] |
|
||||
| [e.g., Maximum inventory size — does the grid have a hard cap or is it infinite-scroll?] | [economy-designer] | [Sprint 3, Day 5] | [Pending] |
|
||||
Reference in New Issue
Block a user