video-accessibility/docs/project/design_guidelines.md
Vadym Samoilenko 6559ccc1f9 feat(help): in-app role-based help guides + screenshot capture pipeline
- Help.tsx: role tabs, TOC scroll-spy, search, lightbox, react-markdown renderer
- 7 markdown guides (global, client, linguist, reviewer, production, PM, admin)
  with explicit click/drag/keyboard annotations throughout
- Sidebar: Help button added at bottom of nav (all roles)
- App.tsx: /help route, no RoleGate
- frontend/public/help-screenshots/{role}/: directories ready for screenshots
- tools/capture-help-screenshots.ts: Playwright screenshot script
  - Clicks "Local login" toggle before filling credentials
  - Uses test-admin local account (not SSO)
- backend/scripts/seed_test_users.py: idempotent MongoDB seed script
  creates 6 local-auth users (admin + 5 roles) for capture + local dev
- .env.screenshots.example: template with test-admin credentials
- Removes docs/video_accessibility_user_guide_v3.md (superseded by in-app guides)
- Deps: react-markdown, remark-gfm, rehype-raw added to frontend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 13:08:13 +01:00

332 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Guidelines — Accessible Video Processing Platform
<!-- SCOPE: UI/UX design system (typography, colors, spacing, grid), component library (navigation, buttons, badges, forms, layout), accessibility guidelines (WCAG 2.1 AA, keyboard, ARIA), responsive behavior (breakpoints), role-based UI. ONLY. -->
<!-- DOC_KIND: explanation -->
<!-- DOC_ROLE: canonical -->
<!-- READ_WHEN: Read when you need visual standards, accessibility rules, or component-level design constraints. -->
<!-- SKIP_WHEN: Skip when you only need implementation details or backend contracts. -->
<!-- PRIMARY_SOURCES: frontend/src/components/, frontend/src/styles/index.css, frontend/tailwind.config.js -->
**Document Version:** 1.0
**Date:** 2026-05-01
**Status:** Active
---
## Quick Navigation
- [Docs Hub](../README.md)
- [Architecture](architecture.md)
- [Tech Stack](tech_stack.md)
- [API Spec](api_spec.md)
## Agent Entry
| Signal | Value |
|--------|-------|
| Purpose | Visual system, accessibility rules, and UI consistency expectations for the React 19 frontend |
| Read When | You need design constraints, token definitions, component patterns, or accessibility guidance |
| Skip When | You only need implementation code or backend/system contracts |
| Canonical | Yes |
| Next Docs | [Architecture](architecture.md), [Tech Stack](tech_stack.md) |
| Primary Sources | `frontend/src/components/`, `frontend/src/styles/index.css`, `frontend/tailwind.config.js` |
---
## 1. Design Approach
### 1.1 Design Philosophy
Clean, professional accessibility-first SaaS platform. The interface prioritises clarity and information hierarchy to support complex multi-language workflows for production teams, QC reviewers, and clients. Dark sidebar + light main content area is the primary shell pattern.
### 1.2 Stack
| Layer | Choice |
|-------|--------|
| CSS framework | Tailwind CSS v4 (utility-first, no component library) |
| Icon system | Inline SVG (24×24 standard, 16×16 compact) |
| Component pattern | Custom React 19 functional components with TypeScript |
| State (server) | TanStack Query v5 |
| State (client) | Zustand v5 |
---
## 2. Core Design Elements
### 2.1 Typography
**Font Families:**
| Role | Font | Weights | Usage |
|------|------|---------|-------|
| Primary / Body | Inter | 400, 500, 600 | All UI text |
| Fallback | system-ui, Avenir, Helvetica, Arial, sans-serif | — | When Inter unavailable |
**Type Scale (Tailwind):**
| Element | Class | Approx Size | Usage |
|---------|-------|-------------|-------|
| Page title | `text-xl font-semibold` | 20px/700 | Navbar page heading |
| Section header | `text-lg font-semibold` | 18px/600 | Card / panel titles |
| Body | `text-sm` / `text-base` | 1416px | Table cells, form labels |
| Caption / badge | `text-xs font-medium` | 12px/500 | Status badges, metadata |
**Line Height:** `leading-normal` (1.5) for body; `leading-tight` (1.25) for headings and compact UI.
---
### 2.2 Color System
**Brand & Interactive:**
| Purpose | Tailwind | Usage |
|---------|----------|-------|
| Primary action | `bg-gradient-to-r from-blue-500 to-blue-600` | Primary CTAs (New Upload, submit) |
| Primary hover | `hover:from-blue-600 hover:to-blue-700` | Primary CTA hover state |
| Link / accent | `#646cff` | Hyperlinks (global CSS) |
**Semantic UI Colors:**
| Purpose | Tailwind classes | Hex approx | Usage |
|---------|-----------------|------------|-------|
| Surface / background | `bg-white` | #ffffff | Cards, main content |
| Sidebar / shell | `bg-gray-900` or dark bg | — | App shell sidebar |
| Navbar | `bg-white shadow-sm border-b border-gray-200` | #ffffff | Top navigation bar |
| Primary text | `text-gray-900` | #111827 | Headings, body |
| Secondary text | `text-gray-600` | #4B5563 | Labels, descriptions |
| Border | `border-gray-200` | #E5E7EB | Card borders, dividers |
| Hover bg | `hover:bg-gray-100` | #F3F4F6 | Button/row hover |
**Status Badge Colors (semantic):**
| State | Tailwind classes |
|-------|-----------------|
| created | `bg-gray-100 text-gray-800` |
| ingesting / translating | `bg-blue-100 text-blue-800` |
| ai_processing | `bg-purple-100 text-purple-800` |
| pending_qc | `bg-yellow-100 text-yellow-800` |
| completed | `bg-green-100 text-green-800` |
| processing_failed / tts_failed | `bg-red-100 text-red-800` |
| qc_feedback | `bg-orange-100 text-orange-800` |
| pending_final_review | `bg-orange-100 text-orange-800` |
| tts_generating | `bg-indigo-100 text-indigo-800` |
| rendering_video / rendering_qc | `bg-violet-100 text-violet-800` |
Source: `frontend/src/utils/jobStatusMessages.ts``getJobStatusColor()`.
**Color Accessibility:** All status badge combinations (light bg / dark text) target WCAG 2.1 AA contrast (4.5:1 for text). Primary blue gradient on white meets 4.5:1 ratio.
---
### 2.3 Layout System
**Spacing Primitives (Tailwind):**
| Token | Value | Usage |
|-------|-------|-------|
| `p-2` | 8px | Icon button padding |
| `px-4 py-2` | 16px / 8px | Compact button |
| `px-6 py-4` | 24px / 16px | Navbar padding |
| `space-x-4` | 16px | Horizontal item gap |
| `gap-6` | 24px | Grid gap |
**Container Strategy:**
| Container | Max Width | Context |
|-----------|-----------|---------|
| Page shell | Full viewport | App layout |
| Main content | `max-w-7xl` (1280px) | Dashboard, job lists |
| Narrow form | `max-w-2xl` (672px) | Upload form, settings |
**App Shell Pattern:**
```text
┌─────────────────────────────────────┐
│ Navbar (h-16, bg-white, shadow-sm) │
├────────────┬────────────────────────┤
│ Sidebar │ Main Content Area │
│ (w-64) │ (flex-1, scrollable) │
│ hidden │ │
│ on mobile │ │
└────────────┴────────────────────────┘
```
**Grid System:** 12-column Tailwind grid, responsive with `grid-cols-1 md:grid-cols-2 lg:grid-cols-3`.
---
### 2.4 Component Patterns
#### Navigation
| Component | Classes | Notes |
|-----------|---------|-------|
| Navbar | `bg-white shadow-sm border-b border-gray-200 px-6 py-4` | Fixed top, h-16 |
| Sidebar | `w-64`, hidden on `< lg` | Role-filtered nav items with badge counts |
| Mobile toggle | `p-2 text-gray-600 hover:bg-gray-100 rounded-lg` | Hamburger, `lg:hidden` |
| Active nav link | `border-l-4 border-blue-500 bg-blue-50 text-blue-700` | Left border indicator |
| Badge counter | `bg-red-500 text-white text-xs rounded-full` | Pending QC / review counts |
#### Buttons
| Variant | Classes | Usage |
|---------|---------|-------|
| Primary | `bg-gradient-to-r from-blue-500 to-blue-600 text-white px-4 py-2 rounded-lg hover:from-blue-600 hover:to-blue-700 shadow-sm hover:shadow-md transition-all duration-200` | Primary CTA, submit |
| Secondary | `text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg p-2 transition-colors` | Icon buttons, secondary actions |
| Destructive | `bg-red-500 text-white hover:bg-red-600` | Delete, reject actions |
Icon size in buttons: `w-4 h-4 mr-2` (leading icon), `w-6 h-6` (standalone icon button).
#### Status Badges
```text
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {status-color-classes}">
```
See Status Badge Colors table above for the full mapping. Source: `src/components/StatusBadge.tsx`.
#### Forms
| Element | Classes |
|---------|---------|
| Input | `border border-gray-300 rounded-lg px-4 py-3 focus:ring-2 focus:ring-blue-500 focus:border-blue-500` |
| Label | `text-sm font-medium text-gray-700 mb-2` |
| Error | `text-red-500 text-sm mt-1` |
| Help text | `text-gray-500 text-sm mt-1` |
Forms use `react-hook-form` v7 for validation. Min touch target: 44×44px.
#### Cards / Panels
| Element | Classes |
|---------|---------|
| Card | `bg-white shadow-md rounded-lg border border-gray-200 p-6` |
| Hover | `hover:shadow-lg transition-shadow duration-200` |
| Interactive | `cursor-pointer hover:border-blue-300` |
#### Dropzone (Upload)
See `src/components/UploadDropzone/`. Uses `react-dropzone` v14. Pattern: dashed border + centered icon + instructional text + drag-active state change.
---
### 2.5 Responsive Behavior
**Breakpoints (Tailwind defaults):**
| Breakpoint | Min Width | Layout adaptation |
|------------|-----------|-------------------|
| default | 0px | Single column, sidebar hidden |
| `md` | 768px | 2-column grids |
| `lg` | 1024px | Sidebar visible, 3-column grids |
| `xl` | 1280px | Full desktop layout |
**Mobile adaptations:**
- Sidebar: hidden, toggled by hamburger button (`lg:hidden` control)
- Tables: horizontal scroll
- Navigation: mobile overlay panel
- Touch targets: min 44×44px on all interactive elements
---
## 3. Accessibility Guidelines
### 3.1 WCAG Compliance
**Target: WCAG 2.1 Level AA** — mandatory, as this platform produces accessibility assets for third parties.
| Criterion | Requirement |
|-----------|-------------|
| Contrast ratio (text) | ≥ 4.5:1 |
| Contrast ratio (UI components) | ≥ 3:1 |
| Focus visible | Visible focus ring on all interactive elements |
| Alt text | All informational images |
| Form labels | All inputs have associated labels |
### 3.2 Keyboard Navigation
- All interactive elements focusable via `Tab`
- Visible focus ring: `focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`
- Logical tab order (top-to-bottom, left-to-right)
- Modal focus trap (Tab cycles within modal when open)
- Skip-to-main link for keyboard users
### 3.3 Screen Reader Support
- ARIA labels on icon-only buttons: `aria-label="Close dialog"`
- Semantic HTML: `<nav>`, `<main>`, `<article>`, `<aside>`
- Form `<label>` elements associated via `for`/`id`
- `aria-live="polite"` for toast/notification messages
- Status updates announced to screen readers
### 3.4 Focus Management
- Focus returns to trigger element after dialog/modal close
- Error messages announced via `aria-live`
- Notification menu uses ARIA landmark roles
---
## 4. Role-Based UI Patterns
The UI adapts based on the authenticated user's role. Role-gated elements are controlled at component level via `useAuthStore()`.
| Role | Visible UI |
|------|-----------|
| `client` | Jobs list (own jobs), New Upload, Downloads |
| `linguist` / `reviewer` | QC queue, VTT editor |
| `production` | All jobs, processing controls |
| `project_manager` | Briefs, final review queue, notifications |
| `admin` | All of the above + Admin panel, Org management |
Sidebar badges reflect pending work counts per role:
- `pending_qc` count → linguist/reviewer/production/admin
- `pending_final_review` count → project_manager/admin
- Failed jobs count → production/admin
- Submitted briefs count → all roles
---
## 5. Page Layout Patterns
### 5.1 Dashboard
Fixed header + sidebar shell. Main area: KPI summary row → filterable jobs table with status badges → pagination. Layout: full-width table inside `max-w-7xl` container.
### 5.2 Job Detail / QC Review
Split panel: video player (left, 60%) + VTT editor (right, 40%). Approval/rejection actions pinned to bottom. Responsive: stacked on `< lg`.
### 5.3 Upload Form
Centred narrow container (`max-w-2xl`). Steps: dropzone → metadata form → language selection → submit. Uses `react-dropzone` + `react-hook-form`.
### 5.4 Admin / Settings
Full-width table layout. Tabs for sub-sections (Users, Organisations, TTS Settings). Tables use standard card wrapper.
---
## 6. Internationalisation
The platform supports 50+ target languages for the content it processes. The UI shell itself is English-only at present. No i18n library is currently used for the UI layer.
---
## Maintenance
**Last Updated:** 2026-05-01
**Update Triggers:**
- New component added or removed from `src/components/`
- Tailwind config changes (breakpoints, theme extensions)
- Color system changes
- Accessibility audit findings
- Role changes affecting navigation visibility
**Verification:**
- [ ] Status badge color table matches `getJobStatusColor()` in `src/utils/jobStatusMessages.ts`
- [ ] Role-based UI section reflects current roles in `useAuthStore()`
- [ ] Color contrast ratios remain WCAG AA compliant
- [ ] Responsive breakpoints match Tailwind config
- [ ] Component patterns verified against actual component files in `src/components/`