# 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/`
