--- phase: 03-collapsible-dashboard-sections plan: 01 subsystem: ui tags: [react, tailwind, radix-ui, i18n, collapsible, dashboard] # Dependency graph requires: - phase: 02-dashboard-charts-and-layout provides: StatCard, SummaryStrip, DashboardPage foundation provides: - CSS animation tokens for collapsible-open/close (index.css) - i18n keys for sections and carryover in en.json and de.json - StatCard with optional subtitle/subtitleClassName props - SummaryStrip with carryoverSubtitle/carryoverIsNegative on balance - DashboardPage carryover subtitle computed and threaded to SummaryStrip - CategorySection presentational collapsible component with header badges and 4-column table - CollapsibleSections container rendering ordered CategorySection list affects: - 03-02 (Plan 02 will wire CollapsibleSections into DashboardContent) # Tech tracking tech-stack: added: [] patterns: - "Presentational components accept t() as prop for i18n decoupling" - "Direction-aware difference logic: spending types over when actual > budget; income/saving/investment over when actual < budget" - "Controlled open state pattern: openSections Record + onToggleSection callback" key-files: created: - src/components/dashboard/CategorySection.tsx - src/components/dashboard/CollapsibleSections.tsx modified: - src/index.css - src/i18n/en.json - src/i18n/de.json - src/components/dashboard/StatCard.tsx - src/components/dashboard/SummaryStrip.tsx - src/pages/DashboardPage.tsx key-decisions: - "CategorySection accepts controlled open/onOpenChange for external state management (Plan 02 will own state)" - "Spending types (bill, variable_expense, debt): diff = budgeted - actual, over when actual > budgeted" - "Income/saving/investment: diff = actual - budgeted, over when actual < budgeted" - "CollapsibleContent uses data-[state=open]:animate-collapsible-open Tailwind variant tied to CSS keyframes" patterns-established: - "Collapsible animation: data-[state=open]:animate-collapsible-open / data-[state=closed]:animate-collapsible-close" - "Category color accent: borderLeftColor via categoryColors[type] inline style" requirements-completed: [UI-DASH-01, UI-COLLAPSE-01] # Metrics duration: 2min completed: 2026-03-17 --- # Phase 3 Plan 01: Collapsible Dashboard Sections (Foundations) Summary **Carryover display wired from DashboardPage through SummaryStrip to StatCard; CategorySection and CollapsibleSections built as pure presentational components with direction-aware difference logic and CSS animation tokens** ## Performance - **Duration:** 2 min - **Started:** 2026-03-17T14:05:37Z - **Completed:** 2026-03-17T14:07:32Z - **Tasks:** 2 - **Files modified:** 8 (6 modified, 2 created) ## Accomplishments - CSS animation tokens (`collapsible-open` / `collapsible-close`) and keyframes added to `index.css` - i18n keys for `dashboard.sections` and `dashboard.carryoverIncludes` added to both `en.json` and `de.json` - `StatCard` extended with optional `subtitle` / `subtitleClassName` props rendered below the value - `SummaryStrip` balance prop extended with `carryoverSubtitle` / `carryoverIsNegative`; threaded to `StatCard` - `DashboardPage` computes carryover subtitle from `budget.carryover_amount` and passes to `SummaryStrip` - `CategorySection` built: left border accent, chevron rotation, budgeted/actual badges, 4-column line-item table with footer totals, direction-aware color coding - `CollapsibleSections` built: thin container with controlled open state, renders ordered `CategorySection` list ## Task Commits Each task was committed atomically: 1. **Task 1: Add CSS animation tokens, i18n keys, and carryover display** - `21ce6d8` (feat) 2. **Task 2: Build CategorySection and CollapsibleSections components** - `f30b846` (feat) **Plan metadata:** (docs commit — see below) ## Files Created/Modified - `src/index.css` - Added collapsible keyframes and animation CSS tokens - `src/i18n/en.json` - Added `dashboard.sections` and `dashboard.carryoverIncludes` keys - `src/i18n/de.json` - Added German equivalents for sections and carryover keys - `src/components/dashboard/StatCard.tsx` - Added optional `subtitle` / `subtitleClassName` props - `src/components/dashboard/SummaryStrip.tsx` - Extended `balance` type with carryover fields - `src/pages/DashboardPage.tsx` - Computed `carryoverSubtitle` / `carryoverIsNegative` and passed to `SummaryStrip` - `src/components/dashboard/CategorySection.tsx` - New: presentational collapsible section component - `src/components/dashboard/CollapsibleSections.tsx` - New: container rendering ordered CategorySection list ## Decisions Made - `CategorySection` uses controlled `open`/`onOpenChange` pattern — Plan 02 will own the open state in `DashboardContent` - Spending types (`bill`, `variable_expense`, `debt`): over-budget when `actual > budgeted` - Income/saving/investment types: over-budget when `actual < budgeted` (under-earning is the "over" condition) - `CollapsibleContent` wired to CSS keyframes via `data-[state=open]:animate-collapsible-open` Tailwind variant ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None. Build passed cleanly. The 6 pre-existing lint errors (MonthNavigator, badge, button, sidebar, useBudgets) were present before this plan and are unchanged — documented in STATE.md as a known concern. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - All presentational building blocks are ready for Plan 02 to wire into `DashboardContent` - `CollapsibleSections` expects: `groups[]`, `currency`, `openSections: Record`, `onToggleSection`, `t` - Plan 02 needs to: group `items` by `CategoryType`, compute per-group totals, manage `openSections` state in `DashboardContent` --- *Phase: 03-collapsible-dashboard-sections* *Completed: 2026-03-17*