- 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
111 lines
5.0 KiB
Markdown
111 lines
5.0 KiB
Markdown
---
|
|
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*
|