Files

21 KiB
Raw Permalink Blame History

Project Research Summary

Project: SimpleFinanceDash — UI/UX Overhaul Milestone Domain: Personal finance budget dashboard (React SPA, UI-only redesign) Researched: 2026-03-16 Confidence: HIGH

Executive Summary

This milestone is a pure UI/UX overhaul of an existing working application. The backend (Supabase schema, hooks, queries) is frozen. The stack is already in place — React 19, Vite 8, Tailwind CSS 4, Recharts 3.8.0, shadcn/ui, TanStack Query — and no new framework dependencies are needed. The overhaul adds three shadcn/ui primitives (chart, accordion/collapsible), extends the existing OKLCH color system, and introduces a structured component hierarchy for the dashboard. The core transformation is from a flat single-chart dashboard to a rich hybrid layout: summary KPI cards, three chart types (donut, vertical bar, horizontal bar), and collapsible per-category line-item sections.

The recommended approach is to establish design foundations first (tokens, shared components, build order primitives) before touching any page. Every visual decision — color, spacing, card style — must originate from index.css @theme inline tokens and a small set of shared components (PageShell, StatCard, CategorySection). Without this discipline, a multi-page overhaul will produce "island redesign" inconsistency: each page looks polished individually but the app feels fragmented during navigation. The dashboard phase comes second, followed by extending the design system to all remaining pages.

The highest-risk technical area is the Recharts + shadcn chart.tsx integration: the official shadcn PR for Recharts v3 is not yet merged, so the generated chart.tsx requires a known manual patch (add initialDimension to ResponsiveContainer). A close second risk is collapsible section layout shift — Recharts ResponsiveContainer instances react to parent height changes, and multiple instances on one page require debounce={50} and Radix Collapsible (not raw display:none toggle) to prevent ResizeObserver cascade errors. Both risks have documented fixes and are LOW recovery cost if addressed proactively.


Key Findings

The stack is locked; no new npm packages are required. Three shadcn/ui components must be installed via CLI: chart (Recharts theme-aware wrappers), collapsible (Radix primitive for category sections), and optionally accordion. After running npx shadcn@latest add chart, a manual one-line fix to chart.tsx is required: add initialDimension={{ width: 320, height: 200 }} to the inner ResponsiveContainer (see shadcn-ui/ui issue #9892). The existing OKLCH color palette in index.css needs only two additions: richer chroma on category colors (bump from ~0.14 to ~0.18+) and semantic status tokens (--color-over-budget, --color-on-budget, --color-budget-bar-bg).

Core technologies and their roles for this milestone:

  • Recharts 3.8.0 — all three chart types (donut, bar, horizontal bar) are supported natively; stay on current version, do not introduce alternative chart libraries
  • shadcn chart.tsxChartContainer + ChartTooltipContent wrappers provide CSS-variable-aware theming for all Recharts instances; required patch documented in issue #9892
  • shadcn Collapsible — Radix UI primitive that animates height via CSS custom property --radix-collapsible-content-height; the correct tool for per-category collapsible sections
  • Tailwind CSS 4 @theme inline — single source of truth for all color tokens; all component color values must reference CSS variables, never hardcoded hex
  • useMemo in DashboardContent — all chart data derivations must be memoized centrally; child chart components receive pre-computed data arrays and render only

Critical version note: Recharts 3 deprecated Cell in favor of shape prop, and removed blendStroke — use stroke="none" instead. Existing Cell usage still works but should not be extended.

Expected Features

Research grounded in competitor analysis (YNAB, Empower) and fintech UX standards. The full feature list lives in FEATURES.md.

Must have (table stakes — users expect these):

  • Summary KPI cards (income / expenses / balance) with colored semantics and variance badges
  • Donut chart with center total label and active hover expand
  • Horizontal bar chart: budget vs actual per category type
  • Grouped bar chart: income budgeted vs actual
  • Collapsible per-category sections with line items and group totals
  • Skeleton loading states that mirror the real layout structure
  • Month navigation control on the dashboard (currently locked to current month)
  • Consistent design language across all pages — the dashboard sets the pattern, all other pages must inherit it

Should have (differentiators, high value for low cost):

  • Variance indicators (delta arrows/badges) on summary cards and section headers
  • Accent-colored category section borders (border-l-4 with category CSS variable)
  • Empty state with actionable CTA for new months
  • Carryover amount surfaced on the dashboard balance card
  • Section collapse state preserved in localStorage (P3 polish)

Defer to v2+:

  • Trend / multi-month charts — requires new query shape and chart layout; explicitly out of scope
  • Dark mode — OKLCH infrastructure is ready but requires full contrast audit; doubles testing surface
  • AI-derived insights — backend dependency; no scope here
  • Drag-to-reorder categories — requires sort_order mutation support

Architecture Approach

The existing three-tier architecture (Pages → Hooks → Supabase) is preserved intact. The overhaul introduces a View Components layer that sits between pages and shadcn/ui primitives, and a small Shared Components layer for cross-page patterns. Hooks and library files are read-only during this milestone; all computation lives in the presentation layer via useMemo.

New components and their responsibilities:

Component Location Responsibility
DashboardContent components/dashboard/ Orchestrator: owns useMemo derivations, passes typed props to all children
SummaryStrip + StatCard components/dashboard/ KPI cards row with semantic color and variance badge
ChartPanel components/dashboard/ Two-column responsive grid containing all three chart instances
IncomeBarChart components/dashboard/ Budgeted vs actual income vertical bar, wrapped in ChartContainer
ExpenseDonutChart components/dashboard/ Expense breakdown donut with center total and custom legend
SpendBarChart components/dashboard/ Horizontal budget vs actual by category type
CategorySection components/dashboard/ Radix Collapsible wrapping header row + BudgetLineItems
BudgetLineItems components/dashboard/ Line-item table reusing existing InlineEditCell / DifferenceCell atoms
PageShell components/shared/ Cross-page consistent header with title, optional description, CTA slot

Build order is strictly dependency-driven (see Architecture section for full sequence): install shadcn primitives first, then PageShell and StatCard, then chart components, then CategorySection, then DashboardContent as final orchestrator, then all remaining page refreshes.

Critical Pitfalls

All six pitfalls in PITFALLS.md are rated HIGH confidence with verified fixes. The top five to actively prevent:

  1. Unmemoized chart data triggers triple re-renders — every items.filter().reduce() in DashboardContent must be wrapped in useMemo. Adding three chart instances to a non-memoized render body multiplies re-render cost 3x and causes tooltip hover lag. Recovery cost is LOW but disrupts delivered work if caught late.

  2. shadcn chart.tsx incompatibility with Recharts 3 — the generated chart.tsx from npx shadcn@latest add chart will produce width(-1) and height(-1) warnings and potential layout failures. Apply the initialDimension fix to ChartContainer immediately after generation. This is a one-line fix with a documented workaround (issue #9892), but if skipped it causes all charts to silently render at zero dimensions.

  3. Collapsible sections trigger ResizeObserver cascade on charts — using display:none toggle or raw height animation on category sections causes Recharts ResponsiveContainer instances above/below to rapidly resize. Fix: use Radix Collapsible with CSS @keyframes on --radix-collapsible-content-height, and add debounce={50} to all ResponsiveContainer instances.

  4. Color accessibility regression during "rich visual" overhaul — the redesign goal of rich colors is a direct risk factor for WCAG contrast failures. The existing text-green-600 / text-red-600 pattern must be audited (green-600 is borderline). All six category pie slice colors cluster at similar OKLCH lightness (~0.650.72) — vary lightness as well as hue. Supplement color with icons for status indicators; color alone is never sufficient.

  5. i18n key regressionsi18next silently falls back to English when German keys are missing (fallbackLng: 'en'). Every new UI text key must be added to both en.json and de.json in the same commit. Run i18next-scanner or manually switch to German locale before marking any phase complete.

Sixth pitfall to prevent at the outset: Design inconsistency across page refreshes. If shared components (StatCard, CategorySection header pattern, card border accents) are not extracted before page work begins, each page will develop subtle visual drift that is expensive to correct retroactively.


Implications for Roadmap

Research points to a clear four-phase structure. The ordering is driven by: (1) the build dependency chain in ARCHITECTURE.md, (2) the "design foundation before page work" principle from PITFALLS.md, and (3) the feature dependency graph in FEATURES.md.

Phase 1: Design Foundation and Primitives

Rationale: Multiple pitfalls converge on the same root cause — design tokens and shared components must exist before any page work begins. Design drift (Pitfall 6) and color accessibility failures (Pitfall 4) both require the palette and shared component abstractions to be established first. This phase has no external dependencies and produces the building blocks every subsequent phase consumes. Delivers: Extended index.css color tokens (richer chroma, semantic status tokens), installed shadcn primitives (chart.tsx with Recharts v3 patch applied, collapsible.tsx), PageShell, StatCard / SummaryStrip components. Addresses: Summary KPI cards (table stakes), accent-colored category borders, semantic color system, skeleton components Avoids: Design inconsistency pitfall, color accessibility regression, CSS variable scope issues Research flag: Standard patterns — no additional research needed. Tailwind v4 @theme inline and WCAG contrast requirements are well-documented.

Phase 2: Dashboard Charts and Layout

Rationale: Charts depend on chart.tsx from Phase 1. The dashboard is the highest-value page and establishes the full visual language for all subsequent pages. Month navigation must be included here (not deferred) because it changes how DashboardContent holds state — retrofitting it after collapsible sections are built is more disruptive than including it upfront. Delivers: DashboardContent orchestrator with useMemo data derivations, ChartPanel with all three chart types (IncomeBarChart, ExpenseDonutChart, SpendBarChart), month navigation control, skeleton loading for charts and cards. Addresses: Donut chart (table stakes), horizontal bar chart (P1), grouped income bar chart (P1), skeleton loading (P1), month navigation (P1) Avoids: Unmemoized chart data pitfall (use useMemo from the start), chart.tsx Recharts v3 patch (apply in Phase 1 before this phase begins) Research flag: Standard patterns — Recharts 3.8.0 chart implementations are fully documented. The specific chart.tsx fix is documented in issue #9892.

Phase 3: Collapsible Dashboard Sections

Rationale: CategorySection depends on Collapsible primitive (Phase 1) and BudgetLineItems (which reuses existing InlineEditCell atoms). This phase brings the dashboard to full feature completeness. Separating it from Phase 2 keeps each phase focused and ensures chart layout is stable before section collapse animations interact with chart resize behavior. Delivers: CategorySection components with Radix Collapsible, BudgetLineItems table, group totals row, variance indicators in section headers, carryover amount on balance card. Addresses: Collapsible sections with line items (P1), totals per section (table stakes), variance indicators (P2), carryover amount (P2) Avoids: Collapsible layout shift pitfall — use Radix Collapsible with CSS keyframe animation and debounce={50} on all ResponsiveContainer instances; never display:none toggle Research flag: Standard patterns — Radix Collapsible API is well-documented. The --radix-collapsible-content-height animation pattern is the established approach.

Phase 4: Full-App Design Consistency

Rationale: The dashboard establishes the design token application patterns. All other pages inherit from it. This phase is sequenced last because it depends on PageShell and the card/color patterns being proven on the dashboard first. FEATURES.md dependency graph makes this explicit: "all-pages redesign depends on dashboard being finished first." Delivers: PageShell applied to all 9 pages, consistent card/color/typography treatment on BudgetDetailPage (highest urgency — users navigate here directly from dashboard), BudgetListPage, CategoriesPage, TemplatePage, LoginPage, RegisterPage, QuickAddPage, SettingsPage. Empty state pattern for new months. Addresses: Consistent design language (table stakes), BudgetDetailPage polish (P1), remaining page polish (P2), empty states (P2) Avoids: i18n key regressions — switch to German locale and run key parity check before completing each sub-page Research flag: Standard patterns — PageShell wrapper is straightforward. The main risk is thoroughness (9 pages), not technical complexity.

Phase Ordering Rationale

  • Foundation before features: Pitfall 6 (design inconsistency) has a HIGH recovery cost. Establishing index.css tokens and shared components in Phase 1 prevents the most expensive failure mode.
  • Dashboard before other pages: FEATURES.md dependency graph is explicit — the dashboard establishes the patterns all pages inherit. Building it second (after foundation) lets Phase 4 apply proven patterns.
  • Charts before collapsibles: ChartPanel layout must be stable before collapsible sections are added beneath it. The ResizeObserver pitfall (Pitfall 3) is easiest to test and fix when charts are the only moving part.
  • Sections in their own phase: The collapsible + ResizeObserver interaction is the trickiest technical integration. Isolating it in Phase 3 limits blast radius if issues arise.

Research Flags

Phases with standard, well-documented patterns (skip /gsd:research-phase):

  • Phase 1: Tailwind v4 @theme inline, OKLCH color tokens, and WCAG contrast requirements are all from official documentation with no ambiguity.
  • Phase 2: Recharts 3.8.0 chart implementations and the chart.tsx fix are fully documented. Month navigation via useBudgets hook is a straightforward state change in DashboardContent.
  • Phase 3: Radix Collapsible primitive is well-documented. The animation pattern with --radix-collapsible-content-height is the standard approach.
  • Phase 4: PageShell application and page-by-page refresh are repetitive pattern application, not novel implementation.

No phases require pre-execution research. All major decisions are resolved by this research.


Confidence Assessment

Area Confidence Notes
Stack HIGH Stack is locked and fully inspected. The one uncertainty (shadcn chart.tsx + Recharts v3 compatibility) has a documented fix in issue #9892.
Features HIGH Grounded in competitor analysis (YNAB, Empower) and fintech UX standards. Feature prioritization is opinionated and defensible.
Architecture HIGH Based on full codebase inspection. Component boundaries and build order are derived from actual file structure and import dependencies.
Pitfalls HIGH Most pitfalls verified against official docs and open Recharts/shadcn issues. Recovery strategies and warning signs documented for each.

Overall confidence: HIGH

Gaps to Address

  • shadcn chart.tsx patch (issue #9892): The initialDimension fix is community-verified but not yet merged into the official shadcn CLI output. Apply manually after generation and verify with a smoke test (render one chart, confirm no width(-1) warnings in console) before proceeding with Phase 2.
  • WCAG contrast on category colors: The recommended OKLCH values in STACK.md (chroma bumped to ~0.18+) have not been run through a contrast checker. During Phase 1, verify each category color pair against its background at the target luminance levels. Adjust chroma or lightness if any pair fails 3:1 (non-text) or 4.5:1 (text) thresholds.
  • i18n key count baseline: Before starting the overhaul, run i18next-scanner (or manually audit en.json vs de.json) to establish a baseline parity count. This makes regression detection in each subsequent phase mechanical rather than manual.
  • BudgetListPage data shape: Research did not inspect BudgetListPage implementation in detail. Phase 4 may uncover layout decisions that conflict with the dashboard's card pattern. Plan for one iteration pass on BudgetListPage specifically.

Sources

Primary (HIGH confidence — official documentation)

Secondary (MEDIUM confidence — community sources, multiple corroborating)

Tertiary (informing but not authoritative)


Research completed: 2026-03-16 Ready for roadmap: yes