- 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>
332 lines
12 KiB
Markdown
332 lines
12 KiB
Markdown
# 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` | 14–16px | 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/`
|