Add detailed frontend UX design spec
This commit is contained in:
4
FAQ.md
4
FAQ.md
@@ -28,6 +28,10 @@ To start with a clean backend state, stop the app and remove the corresponding S
|
|||||||
|
|
||||||
No. The backend loads state from SQLite once during startup into in-memory state and serves requests from memory. Successful state mutations are then written back to SQLite.
|
No. The backend loads state from SQLite once during startup into in-memory state and serves requests from memory. Successful state mutations are then written back to SQLite.
|
||||||
|
|
||||||
|
## Where is the frontend UX plan documented?
|
||||||
|
|
||||||
|
The canonical frontend UX design lives in `UX.md` at the repository root. It defines roles, flows, screen behavior, validation/error handling, responsive behavior, and real-time update expectations to guide implementation.
|
||||||
|
|
||||||
## What does test coverage include?
|
## What does test coverage include?
|
||||||
|
|
||||||
Coverage now includes the entire backend project (`RpgRoller`), including API/hosting/bootstrap code and services. It is no longer restricted to `RpgRoller.Services.*`.
|
Coverage now includes the entire backend project (`RpgRoller`), including API/hosting/bootstrap code and services. It is no longer restricted to `RpgRoller.Services.*`.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Fresh full-stack starter scaffold:
|
|||||||
- `RpgRoller/frontend/`: TypeScript frontend source
|
- `RpgRoller/frontend/`: TypeScript frontend source
|
||||||
- `RpgRoller.Tests/`: xUnit integration-heavy test project
|
- `RpgRoller.Tests/`: xUnit integration-heavy test project
|
||||||
- `RpgRoller.sln`: solution used by local CI script
|
- `RpgRoller.sln`: solution used by local CI script
|
||||||
|
- `UX.md`: frontend UX and interaction design specification (pre-implementation baseline)
|
||||||
|
|
||||||
Test layout:
|
Test layout:
|
||||||
|
|
||||||
|
|||||||
389
UX.md
Normal file
389
UX.md
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
# UX Design Specification - Frontend
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
This document defines the target frontend UX for RpgRoller based on `REQUIREMENTS.md`.
|
||||||
|
It is the design baseline we will iterate on before implementing new frontend code.
|
||||||
|
|
||||||
|
Primary goals:
|
||||||
|
|
||||||
|
- Make campaign play flow fast: select context, roll, see results.
|
||||||
|
- Keep role rules clear: player, GM, and visibility boundaries.
|
||||||
|
- Preserve trust: deterministic behavior, clear validation, append-only log feel.
|
||||||
|
- Keep the interface simple enough for live-session use on desktop and mobile.
|
||||||
|
|
||||||
|
## 2. Scope
|
||||||
|
|
||||||
|
In scope for this UX:
|
||||||
|
|
||||||
|
- Authentication (register/login/logout)
|
||||||
|
- Campaign creation and selection
|
||||||
|
- Character create/edit/activate
|
||||||
|
- Skill create/edit
|
||||||
|
- Skill rolling with public/private visibility
|
||||||
|
- Campaign detail view and campaign log with live updates
|
||||||
|
|
||||||
|
Out of scope for v1 UX:
|
||||||
|
|
||||||
|
- Observer role management UI (future role)
|
||||||
|
- Advanced profile settings
|
||||||
|
- Campaign invitations or approvals
|
||||||
|
- Log filtering/search/export
|
||||||
|
|
||||||
|
## 3. Personas and Permissions
|
||||||
|
|
||||||
|
### Player
|
||||||
|
|
||||||
|
- Can create and edit own characters.
|
||||||
|
- Can create and edit skills on own characters.
|
||||||
|
- Can roll own/authorized character skills.
|
||||||
|
- Can see campaign log entries allowed by visibility rules.
|
||||||
|
|
||||||
|
### GM
|
||||||
|
|
||||||
|
- All player capabilities for owned/authorized characters.
|
||||||
|
- Can create campaigns and choose rulesets.
|
||||||
|
- Can edit characters/skills in campaigns they GM.
|
||||||
|
- Can view all rolls in their campaigns, including private rolls.
|
||||||
|
|
||||||
|
### Future Observer (non-v1)
|
||||||
|
|
||||||
|
- Read-only campaign visibility, no mutation actions.
|
||||||
|
|
||||||
|
## 4. UX Principles
|
||||||
|
|
||||||
|
1. Context first: always show current campaign and active character status at top.
|
||||||
|
2. One action, one confirmation: each mutation gives immediate success/failure feedback.
|
||||||
|
3. Permission-aware UI: hide/disable actions the user cannot perform.
|
||||||
|
4. Real-time clarity: live updates should feel stable, not jittery.
|
||||||
|
5. Progressive disclosure: advanced editing appears only when needed.
|
||||||
|
|
||||||
|
## 5. Information Architecture
|
||||||
|
|
||||||
|
Single-page app with two top-level states:
|
||||||
|
|
||||||
|
- Unauthenticated state
|
||||||
|
- Authenticated workspace
|
||||||
|
|
||||||
|
Authenticated workspace is organized into five persistent regions:
|
||||||
|
|
||||||
|
1. Header status bar
|
||||||
|
2. Campaign context rail
|
||||||
|
3. Character panel
|
||||||
|
4. Skill + roll panel
|
||||||
|
5. Campaign details + log panel
|
||||||
|
|
||||||
|
## 6. Global Layout
|
||||||
|
|
||||||
|
### Desktop (>= 1024px)
|
||||||
|
|
||||||
|
- Top sticky header with app identity, user chip, API/connection status, logout.
|
||||||
|
- Three-column body:
|
||||||
|
- Left: campaign context + quick actions
|
||||||
|
- Middle: characters + skills + roll controls
|
||||||
|
- Right: campaign details + live log
|
||||||
|
|
||||||
|
### Tablet (700px-1023px)
|
||||||
|
|
||||||
|
- Two columns with log panel below details.
|
||||||
|
- Roll controls remain visible without excessive scrolling.
|
||||||
|
|
||||||
|
### Mobile (< 700px)
|
||||||
|
|
||||||
|
- Single column, section cards in this order:
|
||||||
|
1. status/context
|
||||||
|
2. campaigns
|
||||||
|
3. characters
|
||||||
|
4. skills/roll
|
||||||
|
5. details
|
||||||
|
6. log
|
||||||
|
- Sticky bottom "Roll" action when a skill is selected.
|
||||||
|
|
||||||
|
## 7. Key User Flows
|
||||||
|
|
||||||
|
### 7.1 First-time GM flow
|
||||||
|
|
||||||
|
1. Register
|
||||||
|
2. Login
|
||||||
|
3. Create campaign with ruleset
|
||||||
|
4. Create character in campaign
|
||||||
|
5. Activate character
|
||||||
|
6. Create skill
|
||||||
|
7. Roll skill (public/private)
|
||||||
|
8. Confirm result appears in campaign log
|
||||||
|
|
||||||
|
### 7.2 Player joins campaign flow
|
||||||
|
|
||||||
|
1. Register/login
|
||||||
|
2. Select existing campaign from accessible campaigns
|
||||||
|
3. Create character in that campaign
|
||||||
|
4. Activate character
|
||||||
|
5. Add/edit skills
|
||||||
|
6. Roll and view log with visibility rules
|
||||||
|
|
||||||
|
### 7.3 GM oversight flow
|
||||||
|
|
||||||
|
1. Open campaign
|
||||||
|
2. Inspect all visible characters and skills
|
||||||
|
3. Observe all roll events, including private
|
||||||
|
4. Validate campaign progression via append-only log
|
||||||
|
|
||||||
|
## 8. Screen-by-Screen Specification
|
||||||
|
|
||||||
|
## 8.1 App Load and Session Restore
|
||||||
|
|
||||||
|
States:
|
||||||
|
|
||||||
|
- Initial: "Connecting..."
|
||||||
|
- Healthy + anonymous: show auth view
|
||||||
|
- Healthy + logged in: show workspace
|
||||||
|
- API unhealthy: show non-blocking banner with retry CTA
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Call health endpoint first, then rulesets and session context.
|
||||||
|
- If session invalid/expired, clear local authenticated state and show auth view.
|
||||||
|
|
||||||
|
## 8.2 Authentication View
|
||||||
|
|
||||||
|
Elements:
|
||||||
|
|
||||||
|
- Register card:
|
||||||
|
- Username
|
||||||
|
- Display name
|
||||||
|
- Password
|
||||||
|
- Submit
|
||||||
|
- Login card:
|
||||||
|
- Username
|
||||||
|
- Password
|
||||||
|
- Submit
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- Username required
|
||||||
|
- Display name required (register only)
|
||||||
|
- Password required, min length 8 for register
|
||||||
|
|
||||||
|
Feedback:
|
||||||
|
|
||||||
|
- Inline field errors pre-submit
|
||||||
|
- Top-level form error for server rejects (e.g., duplicate username, invalid credentials)
|
||||||
|
- Success message after register
|
||||||
|
|
||||||
|
## 8.3 Workspace Header
|
||||||
|
|
||||||
|
Shows:
|
||||||
|
|
||||||
|
- Logged-in display name + username
|
||||||
|
- Active character summary (name or "None selected")
|
||||||
|
- Current campaign summary (name or "No campaign context")
|
||||||
|
- Live state indicator:
|
||||||
|
- Connected
|
||||||
|
- Reconnecting
|
||||||
|
- Offline fallback
|
||||||
|
|
||||||
|
Actions:
|
||||||
|
|
||||||
|
- Logout
|
||||||
|
- Manual refresh (soft reload campaign state and log)
|
||||||
|
|
||||||
|
## 8.4 Campaign Panel
|
||||||
|
|
||||||
|
Elements:
|
||||||
|
|
||||||
|
- Create campaign form:
|
||||||
|
- Campaign name
|
||||||
|
- Ruleset select (`d6`, `dnd5e`)
|
||||||
|
- Create button
|
||||||
|
- Campaign switcher:
|
||||||
|
- Accessible campaigns list
|
||||||
|
- Current selection badge
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Creating campaign auto-selects it.
|
||||||
|
- Switching campaign updates character/skill/log panels.
|
||||||
|
- If no campaigns exist, show empty state with "Create your first campaign".
|
||||||
|
|
||||||
|
## 8.5 Character Panel
|
||||||
|
|
||||||
|
Elements:
|
||||||
|
|
||||||
|
- Character create/edit form:
|
||||||
|
- Name
|
||||||
|
- Campaign target selector (for move/edit flow)
|
||||||
|
- Save button
|
||||||
|
- Character list for selected campaign
|
||||||
|
- Activate character button
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Distinguish:
|
||||||
|
- Active character (highlight + "Active" pill)
|
||||||
|
- Selected character (for editing/skill operations)
|
||||||
|
- GM sees all campaign characters.
|
||||||
|
- Non-GM sees own characters in selected campaign.
|
||||||
|
|
||||||
|
## 8.6 Skill and Rolling Panel
|
||||||
|
|
||||||
|
Elements:
|
||||||
|
|
||||||
|
- Skill create/edit form:
|
||||||
|
- Skill name
|
||||||
|
- Dice expression
|
||||||
|
- Create / Update actions
|
||||||
|
- Skill picker scoped to selected character
|
||||||
|
- Roll form:
|
||||||
|
- Visibility toggle (`public`, `private`)
|
||||||
|
- Roll button
|
||||||
|
- Last roll preview card:
|
||||||
|
- Result total
|
||||||
|
- Breakdown
|
||||||
|
- Visibility
|
||||||
|
- Timestamp
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
|
||||||
|
- Skill actions disabled until a character is selected.
|
||||||
|
- Roll action disabled until a skill is selected.
|
||||||
|
- On roll success:
|
||||||
|
- update preview instantly
|
||||||
|
- refresh log (or patch in optimistic entry then confirm)
|
||||||
|
|
||||||
|
## 8.7 Campaign Details Panel
|
||||||
|
|
||||||
|
Shows:
|
||||||
|
|
||||||
|
- Campaign metadata: name, ruleset, GM
|
||||||
|
- Characters visible to current user
|
||||||
|
- Skills visible to current user
|
||||||
|
|
||||||
|
Goals:
|
||||||
|
|
||||||
|
- Provide a trusted "current truth" snapshot for context before rolling.
|
||||||
|
|
||||||
|
## 8.8 Campaign Log Panel
|
||||||
|
|
||||||
|
Shows chronological roll entries with:
|
||||||
|
|
||||||
|
- Roller identity
|
||||||
|
- Character + skill
|
||||||
|
- Result and breakdown
|
||||||
|
- Visibility badge
|
||||||
|
- Timestamp
|
||||||
|
|
||||||
|
Visibility handling:
|
||||||
|
|
||||||
|
- Public rolls visible to all participants.
|
||||||
|
- Private rolls visible only to roller and GM.
|
||||||
|
- No placeholders for hidden private rolls (avoid leaking that a hidden event exists).
|
||||||
|
|
||||||
|
Live behavior:
|
||||||
|
|
||||||
|
- SSE-driven refresh when campaign version changes.
|
||||||
|
- Heartbeat-aware connection status.
|
||||||
|
- Recover from disconnect with automatic retry and full log refresh.
|
||||||
|
|
||||||
|
## 9. Validation and Error UX
|
||||||
|
|
||||||
|
Pre-submit client validation:
|
||||||
|
|
||||||
|
- Required field checks for all forms
|
||||||
|
- Password minimum length on register
|
||||||
|
- Local non-empty checks for names and expressions
|
||||||
|
|
||||||
|
Server error mapping:
|
||||||
|
|
||||||
|
| Backend condition | UX behavior |
|
||||||
|
|---|---|
|
||||||
|
| `invalid_username`, `invalid_display_name`, `invalid_password` | Show field-level + summary errors in auth forms |
|
||||||
|
| `duplicate_username` | Register username field error with suggestion to choose another |
|
||||||
|
| `invalid_credentials` | Login summary error only (no account existence hints) |
|
||||||
|
| `invalid_campaign_name`, `invalid_character_name`, `invalid_skill_name` | Field-level inline error |
|
||||||
|
| `invalid_ruleset`, expression validation failures, `invalid_visibility` | Field-level error and helper text with valid examples |
|
||||||
|
| `campaign_not_found`, `character_not_found`, `skill_not_found` | Non-blocking panel alert + auto-refresh relevant list |
|
||||||
|
| `forbidden` | Explain permission rule and remove unavailable actions |
|
||||||
|
| `unauthorized` | Clear session and return to auth view with message |
|
||||||
|
| `no_active_character` | Show empty-state CTA: "Activate a character to continue" |
|
||||||
|
|
||||||
|
## 10. Empty, Loading, and Disabled States
|
||||||
|
|
||||||
|
Required empty states:
|
||||||
|
|
||||||
|
- No campaigns yet
|
||||||
|
- No characters in selected campaign
|
||||||
|
- No skills for selected character
|
||||||
|
- No log entries yet
|
||||||
|
- No active character
|
||||||
|
|
||||||
|
Loading patterns:
|
||||||
|
|
||||||
|
- Skeleton rows for lists
|
||||||
|
- Disabled form actions with spinner when mutation is in flight
|
||||||
|
- Maintain prior data view during refresh to reduce layout jumps
|
||||||
|
|
||||||
|
## 11. Real-Time and Sync Rules
|
||||||
|
|
||||||
|
- Campaign details and log are campaign-scoped.
|
||||||
|
- Subscribe to SSE only when:
|
||||||
|
- user is authenticated
|
||||||
|
- a campaign is selected
|
||||||
|
- On event:
|
||||||
|
- fetch campaign details
|
||||||
|
- fetch campaign log
|
||||||
|
- On SSE failure:
|
||||||
|
- exponential backoff reconnect
|
||||||
|
- status indicator changes to "Reconnecting"
|
||||||
|
- keep manual refresh available
|
||||||
|
|
||||||
|
## 12. Accessibility Requirements
|
||||||
|
|
||||||
|
- Full keyboard operation for all controls.
|
||||||
|
- Visible focus ring and logical tab order.
|
||||||
|
- Labels for every input (placeholder is not label).
|
||||||
|
- Contrast target >= WCAG AA.
|
||||||
|
- Screen reader announcements for:
|
||||||
|
- global success/error toasts
|
||||||
|
- roll result updates
|
||||||
|
- reconnect state changes
|
||||||
|
|
||||||
|
## 13. Content and Copy Guidance
|
||||||
|
|
||||||
|
- Use plain language and short action labels:
|
||||||
|
- "Create Campaign", "Activate Character", "Roll Skill"
|
||||||
|
- Avoid technical jargon unless part of ruleset terms.
|
||||||
|
- Error tone: corrective and direct, no blame.
|
||||||
|
- Date/time format: local time display with ISO tooltip.
|
||||||
|
|
||||||
|
## 14. Visual Direction (for implementation phase)
|
||||||
|
|
||||||
|
- Theme: tabletop utility UI with clear hierarchy, not generic admin dashboard.
|
||||||
|
- Emphasize readability for dense gameplay sessions.
|
||||||
|
- Use color semantics:
|
||||||
|
- success for roll completion
|
||||||
|
- warning for validation needs
|
||||||
|
- neutral badges for visibility and role labels
|
||||||
|
- Keep animation purposeful:
|
||||||
|
- subtle updates for log inserts
|
||||||
|
- connection-status transitions
|
||||||
|
|
||||||
|
## 15. Requirements Traceability
|
||||||
|
|
||||||
|
| Requirement area | UX coverage |
|
||||||
|
|---|---|
|
||||||
|
| User management | Auth view with register/login/logout, secure failure messaging |
|
||||||
|
| Campaign management | Campaign create/select panel, ruleset assignment UI |
|
||||||
|
| Character management | Character create/edit/activate flows, ownership-aware rendering |
|
||||||
|
| Active character context | Persistent header context and activation CTA |
|
||||||
|
| Skill management | Skill form + ruleset-aware validation feedback |
|
||||||
|
| Dice rolling | Visibility toggle + deterministic result display |
|
||||||
|
| Campaign log | Chronological live log with permission filtering |
|
||||||
|
| Edge constraints | Disabled/forbidden/unauthorized handling and recovery UX |
|
||||||
|
|
||||||
|
## 16. Open Questions for Iteration
|
||||||
|
|
||||||
|
1. Should campaign switching be global and persistent across sessions, or per-tab only?
|
||||||
|
2. Do we want inline editing in lists, or keep all edits in dedicated forms?
|
||||||
|
3. Should private rolls be visually marked differently for GM vs roller perspective?
|
||||||
|
4. Is manual log filtering needed for v1 (character/skill/roller), or deferred?
|
||||||
|
5. Should we add lightweight onboarding hints for first-time users?
|
||||||
Reference in New Issue
Block a user