Files

245 lines
21 KiB
Markdown

# Feature Research
**Domain:** Personal finance budget dashboard (UI presentation layer overhaul)
**Researched:** 2026-03-16
**Confidence:** HIGH — grounded in competitor analysis (YNAB, Empower), industry design guides, and direct codebase inspection
---
## Context
This research covers the **presentation layer** only. Backend schema and data model are frozen. The question is: what UI/UX features make a personal finance dashboard feel polished rather than basic, and which of those apply to this project's existing data model (income, bills, variable expenses, debt, savings, investments — budgeted vs actual)?
The existing stack is React 19 + Tailwind CSS 4 + Recharts + shadcn/ui. All chart capabilities already exist in Recharts; this research identifies how to use them well.
---
## Feature Landscape
### Table Stakes (Users Expect These)
Features users assume exist. Missing these = product feels incomplete.
| Feature | Why Expected | Complexity | Notes |
|---------|--------------|------------|-------|
| Summary KPI cards at the top | Every finance dashboard leads with top-line numbers (income, total spend, balance). Users scan these first — it's the entry point to understanding the month. | LOW | Already exists but needs richer visual treatment: larger numbers, colored icons, clearer hierarchy |
| Green/red semantic color coding for over/under budget | Finance convention: green = on track, red = over budget. Violating this creates cognitive friction. | LOW | Already exists on progress bars and difference cells; must be consistent across all new chart types |
| Donut/pie chart for expense category breakdown | Standard visualization for "how is spending distributed." Users expect to see the breakdown at a glance. | LOW | Existing pie is plain; needs inner radius (donut), center total label, and richer color fills |
| Budget vs actual per category | The core comparison every budget tool offers. Users come here specifically to compare what they planned to what they actually spent. | MEDIUM | Existing progress bars satisfy this minimally; new grouped/horizontal bar charts will fulfill it properly |
| Inline value editing on budget detail | Users need to log actuals inline — no one wants a separate form for every line item. | LOW | Already implemented in BudgetDetailPage as InlineEditCell; keep and refine |
| Loading state that reflects page structure | If the page renders blank or flashes, users distrust the data or think it's broken. | LOW | Currently returns `null` during load — skeleton cards matching the final layout are expected |
| Empty state with actionable guidance | A blank dashboard for a new month should tell the user what to do next, not just show nothing. | LOW | Currently shows plain muted text; needs a CTA card pattern |
| Tabular-numeral formatting throughout | Financial amounts must use tabular (monospaced number) alignment so columns read correctly. | LOW | Already applied via `tabular-nums`; extend to all new components |
| Color-coded category identity | Users build a mental map: bills are orange, savings are blue. Consistent color per category type is required everywhere — charts, tables, badges. | LOW | Palette already defined in `index.css` and `palette.ts`; extend consistently to new components |
| Collapsible / grouped sections per category type | Budget detail and dashboard both group items by type. Users expect to expand/collapse groups, especially with many line items. | MEDIUM | BudgetDetailPage already groups by type; dashboard needs collapsible inline sections as new feature |
| Month navigation on the dashboard | Users want to check a prior month without navigating away. "Looking at last month" is a top-3 use case for any budget tool. | MEDIUM | Not in current dashboard (auto-resolves current month only); needs month selector |
| Totals row / footer per section | Standard pattern from spreadsheets. Each category group needs a sub-total visible without counting rows. | LOW | Already in BudgetDetailPage table footer; needs equivalent on dashboard sections |
| Consistent design language across all pages | Auth pages, settings, categories, and budget list must feel like the same product as the dashboard. Inconsistency signals amateur work. | HIGH | Currently only dashboard is styled; all other pages need the same card/color/typography treatment |
### Differentiators (Competitive Advantage)
Features that set the product apart. Not required, but valued.
| Feature | Value Proposition | Complexity | Notes |
|---------|-------------------|------------|-------|
| Grouped bar chart: income budgeted vs actual | Directly answers "Did I earn what I expected this month?" in a single visual. Most basic dashboards skip this, showing only expense charts. | MEDIUM | Recharts `BarChart` with two `Bar` components (budgeted / actual); use category colors |
| Horizontal bar chart: spend by category type (budget vs actual) | Lets users scan over-budget categories at a glance. Horizontal orientation makes labels readable without rotation. | MEDIUM | Recharts `BarChart layout="vertical"` with `XAxis type="number"` and `YAxis type="category"` |
| Donut chart with center total label | Center label turns the chart from decorative into informational — shows total spend while the ring shows distribution. YNAB and Empower both do this. | LOW | Recharts `Label` component inside `Pie` using `viewBox` coordinates for positioned text |
| Active sector hover highlight on donut | Hovering a slice expands it slightly and shows the category name + amount in a tooltip. Feels interactive and polished vs a static chart. | LOW | Recharts `activeShape` with expanded `outerRadius` — supported natively |
| Variance indicator (delta arrows) | Show "▲ 12% over" or "▼ 5% under" beside actual amounts on summary cards and section headers. Transforms raw numbers into directional insight. | LOW | Computed from budgeted/actual; render as small colored badge or arrow icon |
| Accent-colored card borders / icon containers | Rich visual style: each category section gets its palette color as a left border accent or icon container fill. Breaks the sea-of-grey-cards look. | LOW | Tailwind `border-l-4` or `bg-[color]/10` container with category CSS variable |
| Section collapse persisted in localStorage | Remembering which sections are open avoids users re-expanding the same sections every visit. Small touch that signals quality. | LOW | Simple `useState` + `localStorage` read/write; wrap in a `useCollapse` hook |
| Carryover amount visible on dashboard | The budget model already tracks `carryover_amount`. Showing it alongside the available balance makes the "running total" story clear. | LOW | Surface as a fourth summary card or sub-label on the balance card |
| Skeleton loading that mirrors the real layout | Animated skeleton cards/charts during load feel like the app is fast and predictable. Blank screens feel broken. | LOW | shadcn/ui `Skeleton` component already available; wrap summary cards and chart containers |
| Page header with budget month name | Every page in the app should show context: "March 2026 Budget." Users confirm they're looking at the right period immediately. | LOW | Format `budget.start_date` as "Month YYYY" in the page heading |
### Anti-Features (Commonly Requested, Often Problematic)
Features that seem good but create problems in this context.
| Feature | Why Requested | Why Problematic | Alternative |
|---------|---------------|-----------------|-------------|
| Trend / multi-month charts | Users always ask "can I see my spending over 6 months?" | Requires multi-budget data aggregation, a new query shape, and a new chart layout — out of scope for a UI-only overhaul. Adding it half-baked is worse than not adding it. | Explicitly defer to a future milestone. Put a placeholder card with "Coming soon" if needed. |
| Dark mode toggle | Professional apps always have a dark mode. | Tailwind CSS 4 dark mode via class strategy is possible, but requires auditing every component's contrast, chart colors, and skeleton states. Doing it properly doubles testing surface. The OKLCH color system is set up with dark mode in mind, but no dark palette is currently defined. | Define as a future phase deliverable. Keep the existing light-only approach consistent and polished first. |
| Real-time sync / live updates | "What if two tabs are open?" | No backend changes allowed this milestone. Supabase realtime would require schema changes and subscription setup. The current TanStack Query polling pattern is sufficient. | Rely on query invalidation on mutation — already in place. |
| Drag-to-reorder line items | Power users want custom sort order | Category `sort_order` field exists, but updating it requires PATCH calls and animation logic. No backend changes in scope. | Keep current `sort_order` from DB; do not expose drag handles this milestone. |
| Glassmorphism / heavy blur effects | Trendy, visually striking | `backdrop-blur` on many elements is GPU-heavy and can degrade performance on lower-end machines. Also risks reducing text readability on charts. Misapplied, it obscures data rather than enhancing it. | Use solid cards with subtle colored-border accents instead. Reserve `backdrop-blur` for a single hero element if at all. |
| AI / natural language budget insights | Feels modern, seen in apps like Copilot | Requires an AI backend, a new API integration, and user data being sent to a third-party service — none of which are part of a UI-only overhaul. | Surface static insights from computed data instead: "You spent 15% more on bills than budgeted this month." Computed in the frontend, no AI needed. |
| Infinite scroll on budget list | "I have many months of budgets" | Adds complexity to the budget list query and requires scroll position management. The budget list is unlikely to have more than 24 entries in a year of use. | Standard paginated or full list with a search/filter input is sufficient. |
---
## Feature Dependencies
```
Donut Chart with Center Label
└──requires──> Category color system (already exists)
└──requires──> Recharts Label component in Pie (Recharts native)
Horizontal Bar Chart (budget vs actual by type)
└──requires──> Category color system (already exists)
└──requires──> Grouped data by category type (already in DashboardContent)
Grouped Bar Chart (income budget vs actual)
└──requires──> Income items filtered from BudgetItems (already in DashboardContent)
Collapsible Dashboard Sections
└──requires──> Category group data (already derived)
└──enhances──> Section collapse persistence (localStorage)
└──enhances──> Totals row per section (already exists in BudgetDetailPage)
Skeleton Loading
└──requires──> Final layout structure (must design layout first)
└──depends-on──> Summary cards layout (build cards first, then wrap in Skeleton)
Month Navigation on Dashboard
└──requires──> Budgets list query (already in useBudgets)
└──conflicts──> Auto-resolve current month (replace with explicit selection)
Consistent Design Language (all pages)
└──depends-on──> Dashboard redesign being finished first (establishes the design token/component pattern)
└──applies-to──> LoginPage, RegisterPage, CategoriesPage, TemplatePage, BudgetListPage, BudgetDetailPage, QuickAddPage, SettingsPage
Variance Indicators (delta arrows)
└──requires──> budgeted_amount and actual_amount both available (already on BudgetItem)
└──enhances──> Summary cards (add % change sub-label)
└──enhances──> Collapsible section headers (show group variance at a glance)
```
### Dependency Notes
- **Skeleton loading requires final layout:** Don't implement skeleton states until the target card/chart layout is finalized — skeleton shape must mirror real content shape.
- **All-pages redesign depends on dashboard:** The dashboard establishes the color system application patterns (accent borders, card styles, typography scale) that all other pages will inherit.
- **Month navigation conflicts with auto-resolve:** The current pattern auto-finds the budget for the current calendar month. Adding a selector means the dashboard must hold local `selectedBudgetId` state rather than computing it.
- **Donut center label requires Recharts Label:** shadcn/ui's chart system supports this natively via the `Label` component inside `Pie` using `viewBox` coordinates. No new library needed.
---
## MVP Definition
This is a UI overhaul milestone, not a greenfield product. "MVP" here means: what must ship for the redesign to feel complete and polished?
### Launch With (v1 — Dashboard Overhaul)
- [ ] Summary cards with richer visual treatment (larger numbers, semantic color on balance, variance badge) — foundation of the dashboard
- [ ] Donut chart with center total label and active sector hover — replaces existing flat pie
- [ ] Horizontal bar chart (budget vs actual by category type) — new chart, satisfies the key "am I on track" question
- [ ] Grouped bar chart (income budget vs actual) — completes the three-chart suite from the reference
- [ ] Collapsible inline sections per category group on dashboard (with line items + group totals) — replaces current progress bars
- [ ] Skeleton loading states for cards and charts — removes the jarring blank-then-rendered experience
- [ ] Month navigation control (budget period selector) on dashboard — without this the dashboard is locked to current month only
### Add After Dashboard Phase (v1.x — Full App Polish)
- [ ] Consistent card/color design applied to BudgetDetailPage — users navigate here from the dashboard; it must match
- [ ] Consistent design applied to BudgetListPage — entry point from nav, feels disconnected from dashboard without polish
- [ ] Consistent design applied to CategoriesPage and TemplatePage — setup pages; lower urgency but visible gap
- [ ] Consistent design applied to LoginPage and RegisterPage — first impression; polish matters
- [ ] Consistent design applied to QuickAddPage and SettingsPage — utility pages; can ship slightly after core flows
- [ ] Section collapse state persisted to localStorage — nice-to-have UX polish
### Future Consideration (v2+)
- [ ] Trend charts over multiple months — deferred explicitly in PROJECT.md out-of-scope
- [ ] Dark mode — foundational work (OKLCH variables) exists but needs full audit and dark palette definition
- [ ] AI-derived spending insights — requires backend changes; no scope here
- [ ] Drag-to-reorder categories — requires sort_order mutation support
---
## Feature Prioritization Matrix
| Feature | User Value | Implementation Cost | Priority |
|---------|------------|---------------------|----------|
| Summary cards — richer visual treatment | HIGH | LOW | P1 |
| Donut chart with center label + active hover | HIGH | LOW | P1 |
| Horizontal bar chart (spend vs budget by type) | HIGH | MEDIUM | P1 |
| Grouped bar chart (income budget vs actual) | HIGH | MEDIUM | P1 |
| Collapsible dashboard sections with line items | HIGH | MEDIUM | P1 |
| Skeleton loading states | MEDIUM | LOW | P1 |
| Month navigation on dashboard | HIGH | MEDIUM | P1 |
| Consistent design on BudgetDetailPage | HIGH | MEDIUM | P1 |
| Consistent design on BudgetListPage | MEDIUM | LOW | P2 |
| Variance indicators (delta arrows/badges) | MEDIUM | LOW | P2 |
| Accent-colored category section borders | MEDIUM | LOW | P2 |
| Carryover amount visible on dashboard | MEDIUM | LOW | P2 |
| Consistent design on auth/settings/utility pages | LOW | MEDIUM | P2 |
| Section collapse persisted in localStorage | LOW | LOW | P3 |
| Empty state with action guidance | MEDIUM | LOW | P2 |
**Priority key:**
- P1: Must have for the overhaul to feel complete
- P2: Should have; include in same milestone if effort allows
- P3: Nice to have; add as polish after core delivery
---
## Competitor Feature Analysis
| Feature | YNAB | Empower (formerly Personal Capital) | Our Approach |
|---------|------|--------------------------------------|--------------|
| Summary KPI cards | Yes — "Available" balance prominent | Yes — net worth headline | 3 cards: Income / Expenses / Balance |
| Budget vs actual bars | Yes — horizontal category bars with color (green/yellow/red) | Cash flow bars | Horizontal bar chart per category type |
| Donut / pie chart | No (YNAB uses different visualization) | Yes — allocation donut for investments | Donut with center total, colored by category type |
| Collapsible grouped sections | Yes — master categories expand to show sub-categories | No — flat list | Collapsible per category type (income, bills, etc.) |
| Inline editing | Yes — click amount to edit | No | Keep existing InlineEditCell pattern, refine styling |
| Color-coded categories | Yes — status colors (green/yellow/red) | Category colors for accounts | Per-type semantic color (income=green, debt=red/pink, etc.) |
| Month/period navigation | Yes — budget period selector in sidebar | Yes — date range selector | Month selector on dashboard |
| Skeleton loading | Yes — YNAB shows skeleton on load | Yes | Skeleton cards + chart placeholders |
| Variance / delta indicators | Yes — shows "over by $X" inline | Yes — shows gain/loss % | Variance badge on summary cards and section headers |
---
## Chart Design Notes (Recharts-Specific)
These translate research findings into concrete implementation guidance for the Recharts stack.
**Donut chart:**
- Use `innerRadius={60}` to `innerRadius={72}` for a modern ring look (not too thin)
- Place center total using `<Label>` with `content` prop inside `<Pie>` using `viewBox` cx/cy coordinates
- Use `activeShape` with `outerRadius + 10` for hover expansion
- Add `isAnimationActive` to respect `prefers-reduced-motion`
- Legend as a separate `<ul>` below the chart (not Recharts built-in legend) for full styling control
**Horizontal bar chart (budget vs actual by type):**
- `<BarChart layout="vertical">` with `<XAxis type="number">` and `<YAxis type="category">`
- Two `<Bar>` components — one for budgeted (muted/secondary color) and one for actual (category color)
- Set `barSize` to keep bars compact; use `barCategoryGap` for breathing room
- `<LabelList position="right">` for actual amounts visible on bar ends
- Never start X axis at a non-zero value
**Grouped bar chart (income budget vs actual):**
- Standard `<BarChart>` with `layout="horizontal"` (default)
- Two `<Bar>` groups: budgeted (muted fill) and actual (category color)
- `<CartesianGrid vertical={false}>` to reduce visual noise
- Custom `<ChartTooltip>` showing both values with currency formatting
**Color system:**
- All charts must consume CSS variables from the existing OKLCH palette (`var(--color-income)`, etc.)
- Never hardcode hex values in chart components — use the `categoryColors` map from `palette.ts`
- Green/red semantic colors for over/under-budget states must be distinct from category colors
---
## Sources
- [Fintech design guide with patterns that build trust — Eleken (2026)](https://www.eleken.co/blog-posts/modern-fintech-design-guide)
- [Finance Dashboard Design Best Practices — F9 Finance](https://www.f9finance.com/dashboard-design-best-practices/)
- [Budget vs Actual Dashboard — Bold BI](https://www.boldbi.com/dashboard-examples/finance/budget-vs-actual-dashboard/)
- [7 Essential Financial Charts for Personal Finance Visualization — Syncfusion](https://www.syncfusion.com/blogs/post/financial-charts-visualization)
- [Fintech dashboard design — Merge Rocks](https://merge.rocks/blog/fintech-dashboard-design-or-how-to-make-data-look-pretty)
- [Dashboard Design UX Patterns Best Practices — Pencil & Paper](https://www.pencilandpaper.io/articles/ux-pattern-analysis-data-dashboards)
- [shadcn/ui Charts — Donut with center text, Bar charts](https://ui.shadcn.com/charts)
- [Bar Charts Best Practices — Nastengraph / Medium](https://nastengraph.medium.com/bar-charts-best-practices-5e81ebc7b340)
- [Best Color Palettes for Financial Dashboards — Phoenix Strategy Group](https://www.phoenixstrategy.group/blog/best-color-palettes-for-financial-dashboards)
- [The Role of Color Theory in Finance Dashboard Design — Extej / Medium](https://medium.com/@extej/the-role-of-color-theory-in-finance-dashboard-design-d2942aec9fff)
- [Skeleton loading screen design — LogRocket](https://blog.logrocket.com/ux-design/skeleton-loading-screen-design/)
- [Empty state UX examples — Eleken](https://www.eleken.co/blog-posts/empty-state-ux)
- [YNAB / Mint / Empower comparison — The State of Personal Finance Apps 2025](https://bountisphere.com/blog/personal-finance-apps-2025-review)
- [Recharts documentation — recharts.org](https://recharts.github.io/en-US/api/Bar/)
---
*Feature research for: SimpleFinanceDash UI overhaul — presentation layer*
*Researched: 2026-03-16*