diff --git a/FAQ.md b/FAQ.md index 7507391..7ff7d3b 100644 --- a/FAQ.md +++ b/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. +## 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? Coverage now includes the entire backend project (`RpgRoller`), including API/hosting/bootstrap code and services. It is no longer restricted to `RpgRoller.Services.*`. diff --git a/README.md b/README.md index cbd4895..85ac492 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Fresh full-stack starter scaffold: - `RpgRoller/frontend/`: TypeScript frontend source - `RpgRoller.Tests/`: xUnit integration-heavy test project - `RpgRoller.sln`: solution used by local CI script +- `UX.md`: frontend UX and interaction design specification (pre-implementation baseline) Test layout: diff --git a/UX.md b/UX.md new file mode 100644 index 0000000..25dbf8c --- /dev/null +++ b/UX.md @@ -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?