From 53c2bd161439abcd905a076d3096f32820a5128e Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Tue, 17 Mar 2026 15:32:24 +0100 Subject: [PATCH] docs(12-01): complete comparison view plan - ComparisonTable component with 10 attribute rows and sticky label column - Delta highlighting: blue-50 lightest weight, green-50 cheapest price, gray delta text - Compare toggle in thread detail toolbar (visible for 2+ candidates) - All COMP-01 through COMP-04 requirements marked complete --- .planning/REQUIREMENTS.md | 16 +-- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 18 +-- .../12-comparison-view/12-01-SUMMARY.md | 110 ++++++++++++++++++ 4 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 .planning/phases/12-comparison-view/12-01-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 7dc1b45..97e8406 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -9,10 +9,10 @@ Requirements for this milestone. Each maps to roadmap phases. ### Comparison View -- [ ] **COMP-01**: User can view candidates side-by-side in a tabular comparison layout (weight, price, images, notes, links, status) -- [ ] **COMP-02**: User can see relative deltas highlighting the lightest and cheapest candidate with +/- differences -- [ ] **COMP-03**: Comparison table scrolls horizontally with a sticky label column on narrow viewports -- [ ] **COMP-04**: Comparison view displays read-only summary for resolved threads +- [x] **COMP-01**: User can view candidates side-by-side in a tabular comparison layout (weight, price, images, notes, links, status) +- [x] **COMP-02**: User can see relative deltas highlighting the lightest and cheapest candidate with +/- differences +- [x] **COMP-03**: Comparison table scrolls horizontally with a sticky label column on narrow viewports +- [x] **COMP-04**: Comparison view displays read-only summary for resolved threads ### Candidate Ranking @@ -68,10 +68,10 @@ Which phases cover which requirements. Updated during roadmap creation. | Requirement | Phase | Status | |-------------|-------|--------| -| COMP-01 | Phase 12 | Pending | -| COMP-02 | Phase 12 | Pending | -| COMP-03 | Phase 12 | Pending | -| COMP-04 | Phase 12 | Pending | +| COMP-01 | Phase 12 | Complete | +| COMP-02 | Phase 12 | Complete | +| COMP-03 | Phase 12 | Complete | +| COMP-04 | Phase 12 | Complete | | RANK-01 | Phase 11 | Complete | | RANK-02 | Phase 11 | Complete | | RANK-03 | Phase 10 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index e2a8672..6215649 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -42,7 +42,7 @@ - [x] **Phase 10: Schema Foundation + Pros/Cons Fields** — Migrate schema and deliver pros/cons annotation UI (completed 2026-03-16) - [x] **Phase 11: Candidate Ranking** — Drag-to-reorder priority ranking with rank badges (completed 2026-03-16) -- [ ] **Phase 12: Comparison View** — Side-by-side tabular comparison with relative deltas +- [x] **Phase 12: Comparison View** — Side-by-side tabular comparison with relative deltas (completed 2026-03-17) - [ ] **Phase 13: Setup Impact Preview** — Per-candidate weight and cost delta against a selected setup ## Phase Details @@ -83,7 +83,7 @@ Plans: 2. The lightest candidate column is highlighted and all other columns show their weight difference relative to it; the cheapest candidate is highlighted similarly for price 3. The comparison table scrolls horizontally on a narrow viewport without breaking layout; the attribute label column stays fixed on the left 4. A resolved thread shows the comparison table in read-only mode with the winning candidate visually marked -**Plans:** 1 plan +**Plans:** 1/1 plans complete Plans: - [ ] 12-01-PLAN.md — ComparisonTable component + compare toggle wiring in thread detail @@ -113,5 +113,5 @@ Plans: | 9. Weight Classification and Visualization | v1.2 | 2/2 | Complete | 2026-03-16 | | 10. Schema Foundation + Pros/Cons Fields | v1.3 | 1/1 | Complete | 2026-03-16 | | 11. Candidate Ranking | 2/2 | Complete | 2026-03-16 | - | -| 12. Comparison View | v1.3 | 0/1 | Not started | - | +| 12. Comparison View | 1/1 | Complete | 2026-03-17 | - | | 13. Setup Impact Preview | v1.3 | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 8c2db52..9ccec7e 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.3 milestone_name: Research & Decision Tools status: planning -stopped_at: Completed 11-candidate-ranking/11-02-PLAN.md -last_updated: "2026-03-16T21:39:11.967Z" +stopped_at: Completed 12-comparison-view/12-01-PLAN.md +last_updated: "2026-03-17T14:32:04.704Z" last_activity: 2026-03-16 — Roadmap created for v1.3 milestone progress: total_phases: 4 - completed_phases: 2 - total_plans: 3 - completed_plans: 3 + completed_phases: 3 + total_plans: 4 + completed_plans: 4 percent: 0 --- @@ -53,6 +53,7 @@ Progress: [░░░░░░░░░░] 0% | Phase 10-schema-foundation-pros-cons-fields P01 | 6min | 2 tasks | 9 files | | Phase 11-candidate-ranking P01 | 4min | 2 tasks | 8 files | | Phase 11-candidate-ranking P02 | 4min | 3 tasks | 7 files | +| Phase 12-comparison-view P01 | 2min | 2 tasks | 3 files | ## Accumulated Context @@ -72,6 +73,9 @@ Key v1.3 research findings (see research/SUMMARY.md): - [Phase 11-candidate-ranking]: Applied sort_order migration via sqlite3 CLI directly to avoid Drizzle data-loss warning on existing rows - [Phase 11-candidate-ranking]: Resolved thread list view uses plain div (not Reorder.Group) — no drag, rank badges visible - [Phase 11-candidate-ranking]: RankBadge exported from CandidateListItem for reuse in CandidateCard grid view +- [Phase 12-comparison-view]: ATTRIBUTE_ROWS declarative array pattern for ComparisonTable keeps JSX clean and row reordering trivial +- [Phase 12-comparison-view]: Compare toggle only shown for 2+ candidates; Add Candidate hidden in compare view (read-only intent) +- [Phase 12-comparison-view]: Weight/price highlight color takes priority over amber winner tint when both apply (more informative) ### Pending Todos @@ -83,6 +87,6 @@ None active. ## Session Continuity -Last session: 2026-03-16T21:30:15.459Z -Stopped at: Completed 11-candidate-ranking/11-02-PLAN.md +Last session: 2026-03-17T14:32:04.702Z +Stopped at: Completed 12-comparison-view/12-01-PLAN.md Resume file: None diff --git a/.planning/phases/12-comparison-view/12-01-SUMMARY.md b/.planning/phases/12-comparison-view/12-01-SUMMARY.md new file mode 100644 index 0000000..72a0e3d --- /dev/null +++ b/.planning/phases/12-comparison-view/12-01-SUMMARY.md @@ -0,0 +1,110 @@ +--- +phase: 12-comparison-view +plan: "01" +subsystem: ui +tags: [react, tailwind, comparison-table, zustand, framer-motion] + +# Dependency graph +requires: + - phase: 11-candidate-ranking + provides: RankBadge component and sort_order-based candidate ordering + - phase: 10-schema-foundation-pros-cons-fields + provides: pros/cons fields on CandidateWithCategory type +provides: + - ComparisonTable component with sticky label column and horizontal scroll + - candidateViewMode "compare" value in uiStore + - Compare toggle in thread detail toolbar (visible when 2+ candidates) + - Weight/price delta highlighting with best-cell color coding + - Resolved thread winner column marking (amber tint + trophy) +affects: [future comparison features, thread detail enhancements] + +# Tech tracking +tech-stack: + added: [] + patterns: + - Declarative ATTRIBUTE_ROWS array pattern for table row rendering (key, label, render, cellClass) + - useMemo delta computation for best-cell identification in comparison views + +key-files: + created: + - src/client/components/ComparisonTable.tsx + modified: + - src/client/stores/uiStore.ts + - src/client/routes/threads/$threadId.tsx + +key-decisions: + - "ATTRIBUTE_ROWS declarative array pattern keeps JSX clean and row reordering trivial" + - "cellClass function pattern in ATTRIBUTE_ROWS allows per-row cell styling without duplicating winner-check logic in every render" + - "Compare toggle only shown when >= 2 candidates (locked decision from plan)" + - "Add Candidate button hidden in compare view — compare is for reading, not mutation" + - "Winner highlight priority: weight/price color wins over amber tint when both apply (more informative)" + +patterns-established: + - "Declarative table row config: ATTRIBUTE_ROWS array with { key, label, render, cellClass } objects" + - "Sticky left column pattern: sticky left-0 z-10 bg-white on every label cell for scroll bleed prevention" + +requirements-completed: [COMP-01, COMP-02, COMP-03, COMP-04] + +# Metrics +duration: 2min +completed: 2026-03-17 +--- + +# Phase 12 Plan 01: Comparison View Summary + +**Side-by-side candidate comparison table with sticky labels, weight/price delta highlighting, and resolved-thread winner marking via a new "compare" candidateViewMode** + +## Performance + +- **Duration:** 2 min +- **Started:** 2026-03-17T14:28:12Z +- **Completed:** 2026-03-17T14:30:00Z +- **Tasks:** 2 +- **Files modified:** 3 + +## Accomplishments +- Built ComparisonTable component with 10 attribute rows (Image, Name, Rank, Weight, Price, Status, Link, Notes, Pros, Cons) using declarative ATTRIBUTE_ROWS pattern +- Implemented useMemo delta computation — lightest weight cell highlighted blue-50, cheapest price cell green-50, non-best cells show gray +delta string +- Sticky left column with bg-white prevents content bleed-through on horizontal scroll +- Amber tint + trophy icon on winner column in resolved threads; weight/price color takes priority when winner is also best +- Extended uiStore candidateViewMode to "list" | "grid" | "compare" and wired compare toggle in thread detail toolbar +- Compare toggle only appears when thread has 2+ candidates; Add Candidate button hidden in compare view +- All 135 existing tests pass, no regressions + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Build ComparisonTable component** - `e442b33` (feat) +2. **Task 2: Wire compare toggle and ComparisonTable into thread detail** - `5b4026d` (feat) + +## Files Created/Modified +- `src/client/components/ComparisonTable.tsx` - New comparison table component with all 10 attribute rows, delta computation, sticky labels, and winner highlighting +- `src/client/stores/uiStore.ts` - Extended candidateViewMode union to include "compare" +- `src/client/routes/threads/$threadId.tsx` - Added ComparisonTable import, compare toggle button (columns-3 icon), ComparisonTable rendering branch, and "Add Candidate" hidden in compare view + +## Decisions Made +- ATTRIBUTE_ROWS declarative array pattern keeps table JSX clean and row reordering trivial — each row is just { key, label, render, cellClass } +- cellClass function in ATTRIBUTE_ROWS allows per-row cell styling without duplicating winner-check logic in every render function +- Compare toggle only shown for 2+ candidates per locked plan decision +- Add Candidate button hidden in compare view to keep toolbar uncluttered (users switch to list/grid to add) +- When winner IS also the lightest/cheapest, weight/price color (blue/green) takes priority over amber tint — more informative + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered +- Minor formatting differences caught by Biome auto-formatter (indentation depth in conditional JSX) — resolved with `biome check --write`. No logic changes. + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- ComparisonTable is complete and functional; compare mode wired end-to-end in thread detail +- No blockers — ready for any follow-on comparison view enhancements +- All existing tests pass; no backend changes needed + +--- +*Phase: 12-comparison-view* +*Completed: 2026-03-17*