Files
brain-of-reese/.agent/user_stories/responsive-polish.md
T
ducoterra 022da8e2bc feat: scaffold Brain of Reese — FastAPI RAG chat over Postgres 17 + pgvector
Foundation (phase 01, verified):
- FastAPI app: /api/health, /api/suggestions, /api/chat (placeholder),
  static frontend served locally (no CDN)
- Postgres 17 + pgvector via db/Containerfile + compose.yaml
  (podman compose up -d db), Alembic initial migration (documents,
  chunks with vector(768), query_log)
- LLM client targeting https://aipi.reeseapps.com/v1 (turbo/embed);
  scripts/llm_probe.py verified models + 768-dim embeddings live
- Conditional debugpy: imported only when DEBUGPY=1 (attach on demand,
  :5678); logging config for clean single-line logs
- Frontend shell: mobile-first chat + Sources pages, tokens, a11y baselines
- Tests: 24 unit+integration (99% coverage on app/), ruff + pyright clean,
  Playwright smoke E2E (3 tests) against a deterministic mock LLM
- Planning: .agent/PLAN.md (architecture + LOCKED decisions), AGENTS.md,
  6 user stories, 7 phase files (one story / one phase / one Playwright
  suite each)
2026-08-21 13:42:21 -04:00

3.5 KiB

Story: Responsive, Polished, Accessible UI

Phase: 07_story_responsive_polish.md · E2E: tests/e2e/test_responsive_polish.py

Narrative

As a user on any device — phone at the coffee shop, laptop at the desk — I want the chat to be comfortable to read and drive: no pinched layout, no tiny tap targets, no contrast failures, no wasted whitespace — so asking Brain feels effortless everywhere.

  • Given any viewport from 360px to 1600px+
  • When I use the chat and the Sources page
  • Then the layout follows the PLAN §7 standards (containers, chat column, full-width table), all interactive elements are reachable by keyboard, and every color pair meets WCAG 2.1 AA.

Acceptance criteria

  1. Layout: container 72rem centered with side padding; chat column capped at 46rem centered; Sources table uses full container width with horizontal scroll below 640px (never a squeezed single hairline column).
  2. Mobile (375px): header condenses, composer reachable above the home indicator (safe-area-inset-bottom), chips scroll horizontally, bubbles ≤92% width, no horizontal page overflow (document scrollWidth == clientWidth).
  3. A11y sweep: landmarks present on both pages (header/nav/main/ footer); skip link works (focus #main); all inputs have labels (visible or programmatically associated); all icon-only buttons have aria-label; :focus-visible outline on every control (Tab through).
  4. Contrast: automated check of the key pairs (ink/surface, ink-soft/surface, white/brand, chip-ink/chip-bg, deflection pairs) ≥4.5:1 (test computes from computed styles; PLAN §7.2 table is the baseline).
  5. No-CDN re-verification on both pages (no http(s):// src/href except same-origin /…).
  6. Reduced motion: with prefers-reduced-motion, typing dots and spinner do not animate (computed animation: none or duration ≥2s).
  7. Long words/paths (e.g. a 60-char file path) wrap or ellipsize without breaking the bubble (overflow-wrap anywhere).

UI Visualization & Structure

  • This phase is the visual audit + fix pass: it does not add features, it enforces PLAN §7 end-to-end on chat + sources.
  • Desktop 1440px screenshot pass: header 64px, chat centered with balanced margins, sources table edge-to-edge within the container.
  • Tablet 768px: chat column uses most of the width (≤46rem cap), no mid-column dead zones; stat cards 3-across.
  • Phone 375px: one-column flow, 44px+ targets, thumb-zone composer.
  • Any deviation found → fix in frontend/assets/styles.css (tokens first), re-verify with the E2E below.

Playwright Mapping Rule

Test Scenario → tests/e2e/test_responsive_polish.py:

  1. test_no_horizontal_overflow_at_viewports — for 360/375/768/1280/1600: document.documentElement.scrollWidth <= clientWidth on both pages.
  2. test_chat_column_capped_and_centered — at 1600px, .chat-shell width ≤ 46rem (736px) + 2% and horizontally centered (±2%).
  3. test_sources_table_full_width — at 1280px, .table-wrap width ≥ 80% of .container width.
  4. test_a11y_landmarks_and_labels — both pages: landmarks present, skip link target #main focusable, #message-input has an associated label, no <img>/icon buttons without accessible name.
  5. test_contrast_pairs_pass_aa — computed-color contrast assertions for the PLAN §7.2 pairs (helper computes WCAG relative luminance).
  6. test_reduced_motion_respected — emulate reducedMotion: 'reduce'; typing dots have no running animation (or ≥2s duration).