Files
brain-of-reese/.agent/phases/todo/05_story_suggestion_chips.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

2.5 KiB
Raw Blame History

Phase 05 — Story: Suggestion Chips

Story: .agent/user_stories/suggestion-chips.md Context: .agent/PLAN.md §7 (UI/UX), story file for chip spec

Goal

Zero-friction onboarding: 3–4 real example questions on first load, clickable → filled → submitted, keyboard-first, mobile-scrollable.

Implementation steps

  1. app/config.py — confirm suggestions is env-overridable (BOR_SUGGESTIONS as JSON list via pydantic-settings) and tune the defaults against the actually imported Homelab/Deployments topics (read a sample of documents titles; pick questions real answers exist for).
  2. app.js — extract a renderChips(container, items, {onSelect}) helper; real <button type="button" class="suggestion-chip" role="listitem"> inside #suggestions[role="list"]; onboarding onSelect = fill #message-input + focus + composer.requestSubmit(). Reuse the same helper for deflection chips (Phase 04) with the same submit behavior.
  3. Empty-state lifecycle: first user message hides #empty-state (already done in addMessage) — verify chips don't linger in the conversation.
  4. Mobile CSS check: chip row nowrap + overflow-x auto at ≤640px (tokens already exist — verify, don't duplicate).

UI Verification

Against the story: pills 999px radius, ≥44px, brand-soft/brand-ink (≥6:1), hover/active states; desktop centered wrap vs mobile single scroll row; Tab order reaches chips before the composer input is required; screen reader: group labeled "Suggested questions". Screenshot pass 1280px + 375px.

Testing & Quality

  • Unit/integration: GET /api/suggestions honors BOR_SUGGESTIONS env override (JSON list); default list has ≥3 non-empty strings.
  • Coverage: >90% on app/ (JS is covered by E2E).

Playwright Execution Phase

Run ONLY this story's suite:

uv run pytest tests/e2e/test_suggestion_chips.py -v --no-cov

Implements the story mapping: chips render (≥3, role=list); chip click submits (user bubble with exact chip text + mock reply); keyboard Tab+Enter activates; 375px chip row is a horizontal scroll row.

Success criteria

  • onboarding chips render from the API; click = one-tap question
  • keyboard + SR usable; mobile scroll row
  • deflection chips share the component + submit behavior
  • unit + integration green, coverage >90%
  • story E2E green in isolation
  • committed

Commit

git add -A && git commit --no-gpg-sign -m "feat(ui): onboarding suggestion chips with one-tap submit, keyboard access, and mobile scroll row"