Commit Graph

23 Commits

Author SHA1 Message Date
null 522eaaf101 chore(deps)!: tailwind 3 -> 4 via @tailwindcss/vite (4i)
Official codemod (run in a clean worktree; docker-owned data/ blocks it
in-tree): tailwind.config.js inlined into client/index.css as CSS-first
@theme/@utility (config file deleted — v4 auto-detects content, which
also retires the .tsx-content-glob failure class from the TS migration),
33 template files' class renames applied, tailwindcss-animate loads via
the v4 @plugin bridge. Build runs through @tailwindcss/vite; postcss
config is now plugin-free. tailwind-merge -> 3 (v4 class model).

Visual-regression gate: only diffs were a ~2px global preflight shift +
the version string (baseline predated 0.41.1); re-baselined both login
screenshots in this commit after review. webauthn.probe confined to the
probe project (it enables WebAuthn for the seeded user, racing the
parallel UI projects' password logins).

e2e 27 passed, probe 18/18, PROD SMOKE PASS, typecheck/lint/tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:03:15 -05:00
null f587d09d4a style: apply Prettier across client + server (no behavior change)
One-time repo-wide `prettier --write` (isolated commit so future diffs
stay reviewable). Mechanical formatting only.

Verified unchanged: typecheck + typecheck:server + check:server clean;
server tests 232/232; client tests 50/50; Vite build succeeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 14:23:53 -05:00
null c41f1a8a7b feat(tracker): status row border-left indicators, refined metric cards, search filter, and CSS polish 2026-07-06 13:47:34 -05:00
null df1f61d6cc feat(brand): render the real product glyph SVGs (not inline approximations)
BrandGlyph drew hardcoded monochrome shapes from an inline switch and
ignored the actual /brand/glyphs/*.svg files. Render the real files via a
robust <img> (fail-soft onError, intrinsic width/height so no layout
shift, alt for a11y parity) so every existing placement — PageHeader
(Tracker/About/Release), Command Palette, Release Notes, Onboarding,
Login — shows the full-color brand tiles. Deletes the ~85-line dead
BrandGlyphShape switch and the now-unused useId import.

Senior-review while-here:
- Guard test (client/lib/brand.test.ts): asserts every BrandGlyphName
  asset — and every /brand asset in brand.ts — resolves to a real,
  non-empty file on disk. Catches the "image added but path wrong /
  renamed" regression TS can't see.
- Widen vitest include to {js,jsx,ts,tsx}: TypeScript client tests were
  silently never run (client/hooks/useAutoSave.test.ts). Now 6 files / 50
  tests run (was 4 / 42).
- Remove dead brand.ts entries: legacyLogo (pointed at the OLD pre-brand
  /img/logo.png) and the unused ADMIN_GLYPH const.
- PageHeader glyph class inline-grid -> inline-block for the <img>.

Verified: typecheck + lint clean; test:client 50/50; build (glyphs land
in dist/brand/glyphs, served 200 as image/svg+xml); e2e probe 17/17;
login visual baseline unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 13:32:37 -05:00
null c2b6a7d1b4 refactor(brand): adopt new primitives in ui/{button,card,badge}
The three shadcn primitives get the small adjustments the new
design-token set calls for — shadow, ring, and border tokens that
align with the index.css overhaul, and tone helpers that defer to
the tokens the primitives export. 20 lines total, no behaviour
change: same variants, same API, same default sizes.

This is commit 4 of 9 in the v0.42.0 brand refresh. Depends on
36834e6 (layout chrome + index.css tokens).
2026-07-05 17:18:38 -05:00
null 4898987a18 feat(brand): shared app-primitives UI kit
Adds the cross-cutting UI primitives the rest of the brand refresh
consumes. The 159-line file bundles the small, repeated bits every
page/dialog needs so the per-page commits can stay minimal:

- TonedCard: bordered card with neutral / good / warn / danger / info
  variants (border + bg + text per tone), consumed by the
  overdue/summary/bank-sync cards.
- ToneDot: small status dot for the new badges.
- EmptyState: lucide Inbox + heading + body used for filtered-empty
  and zero-data states.
- SectionHeading / FieldRow: small typographic primitives for the
  Settings / Profile / Admin pages.
- BrandGlyph (re-export of the Brand module) so consumers only need
  to import from '@/components/ui/app-primitives'.

This is commit 2 of 9 in the v0.42.0 brand refresh. Depends on
dfee7f9 (brand module); consumed by the layout/UI/consumer commits.
2026-07-05 17:18:23 -05:00
null e2d4a9f703 feat(settings): theme "System" + reduce-motion (plan Tier 1)
- ThemeContext gains a 'system' theme that follows prefers-color-scheme and
  updates live when the OS flips; exposes resolvedTheme (consumed by Sonner) and
  keeps the <meta theme-color> in sync. Pre-bundle inline script in index.html
  prevents a light/dark flash. Both theme selectors (Settings ThemeCards +
  theme-toggle dropdown) gain the System option.
- New MotionPreferenceContext mounts framer-motion <MotionConfig>; a Reduce-motion
  toggle (localStorage device pref) forces reducedMotion="always" (else "user",
  which still respects the OS).
- Add an accessible SettingHelp tooltip (focusable button + aria-label) wrapped by
  a page-level TooltipProvider; used for the System + Reduce-motion explanations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:50:37 -05:00
null 3973560e92 refactor(tracker): remove dead code and unreferenced files (plan A1)
- Delete unreachable in-file dialogs: MonthlyStateDialog block (setShowMbs
  never called) and inline PaymentModal in TrackerRow + MobileTrackerRow
  (setEditPayment only ever null; editing works via PaymentLedgerDialog).
- Delete fully-unreferenced files: tracker/EditableCell.tsx,
  ui/confirm-dialog.tsx, ui/separator.tsx (+ orphaned @radix-ui/react-separator).
- Simplify OverdueCommandCenter dead branch (early-returns null when empty).
- Correct stale roadmap/FUTURE docs: tracker keyboard nav is implemented.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 14:35:13 -05:00
null 1f18a720c4 refactor(ts): convert all UI primitives + ThemeContext to TSX (B2)
Foundational for phase B: the ui/* primitives were untyped .jsx, and TS infers
React-19 ref-as-prop components as *requiring* a ref, so every consumer errored.
Converted all 22 ui primitives (button, input, card, dialog, select, table,
dropdown-menu, tabs, badge, checkbox, switch, tooltip, separator, label,
Skeleton, collapsible, alert-dialog, sonner, save-status, theme-toggle,
input-dialog, confirm-dialog) using ComponentProps<'el'> / ComponentProps<typeof
Radix.X> + VariantProps for cva components — refs now optional, event params
typed. Also converted ThemeContext.tsx (createContext(null) made useContext's
post-guard return `never`, so setTheme was uncallable — fixed with a typed
context value) and three tracker cells (EditableCell/NotesCell/
LowerThisMonthButton) that consume the branded TrackerRow.

Added a shared errMessage(unknown) helper to utils (strict catch → unknown);
usePaymentActions reuses it. TrackerRow gains monthly_notes + amount_suggestion
(real server fields).

typecheck 0, lint 0 errors (42 warns), build green, 48 client tests. NOTE: the
e2e auth-setup probe is currently red on an unrelated, pre-existing
release-notes-modal dismissal race (reproduces on the last known-good commit;
the a11y snapshot shows these converted primitives rendering correctly) —
investigating separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 22:57:22 -05:00
null b8d394061b fix(client): resolve all 13 exhaustive-deps warnings (R2b)
- BankSyncSection: handleBtSave read btLateGraceDays but it was missing from the
  useCallback deps -> saving could persist a STALE late-grace value (real bug).
- ProfilePage: EditProfile sync effect now depends on [profile].
- Stabilized identity of derived arrays/objects feeding useMemo deps (they were
  recreated every render, defeating memoization): TrackerPage filters + rows,
  HealthPage bills, BankTransactionsPage transactions -> wrapped in useMemo.
- BillModal + TransactionMatchingSection: intentional id/filter-scoped effects
  documented with a targeted eslint-disable + reason.
- Removed 2 stale eslint-disable directives (confirm-dialog, useAuth).

exhaustive-deps + rules-of-hooks now both 0. Build + client tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 19:47:14 -05:00
null d9a441dff6 feat(settings): auto-save preferences with live save status (batch 0.39.0)
Replace all Save buttons on the Settings page with debounced auto-save:

- useAutoSave hook: debounce with latest-payload-wins, flush() for blur,
  pending-edit flush on unmount, status machine (idle/saving/saved/error)
  with saved fading back to idle. Covered by 6 Vitest tests (fake timers).
- SaveStatus pill (framer-motion) in the page header and notification card
  headers — Saving…/Saved/Save failed.
- Timing per control: toggles/selects/channel ~150-400ms; typed inputs
  (email, URLs, grace period, drift pct) 900ms + flush on blur.
- Push token never auto-saves mid-type: saves on blur only, so a partial
  token can never overwrite a working one.
- Notification cards no longer refetch parent settings on save (would
  clobber in-flight edits under auto-save).
- Decision: no undo toast — settings are non-destructive and instantly
  re-editable; undo would add noise without safety.
- vitest include now picks up .jsx tests; jsdom + @testing-library/react
  added as devDependencies.
2026-06-12 02:08:42 -05:00
null 68aa5eff31 fix(snowball): plan history and bill modal updates 2026-06-07 19:13:16 -05:00
null ec7869abbc feat: framer-motion page transitions and UI polish 2026-06-07 15:14:09 -05:00
null 3b555e4d8e chore: shadcn/ui component updates (batch) 2026-06-07 14:29:09 -05:00
null 792980b8ba style: stronger late/missed payment visibility
- Tracker rows, mobile rows: alert icons, left-edge marker, stronger row tinting
- Calendar grid and detail dialog: brighter dots, count badges
- StatusBadge: stronger orange/rose badges for late/missed
- Shared badge component: clearer contrast
2026-05-28 23:42:46 -05:00
null a1f679f7b0 style: global readability/theme pass
- Sharpened font stack in index.css, removed softer Georgia digit font for UI text/money
- Tuned dark-mode tokens: clearer foreground, brighter muted text, stronger borders, defined cards
- Updated UI primitives: cards, buttons, inputs, selects, tables, badges
- Cleaned up bills rows, mobile bill rows, tracker dismiss, snowball icons, summary/category/health/analytics money values, import/export status icons
- Reduced fuzzy uppercase label spacing globally
2026-05-28 23:18:14 -05:00
null 0ba315bd32 v0.28.0 2026-05-15 22:45:38 -05:00
null 2ce5328fd2 v0.25.0: roadmap redesign, import CSRF fix, AdminDashboard removed
- RoadmapPage: kanban-style priority lanes, shadcn Collapsible/Tabs,
  lazy-loaded activity log, admin-only /api/about/roadmap + /dev-log endpoints
- Import CSRF fix: added x-csrf-token header to importAdminBackup,
  previewSpreadsheetImport, previewUserDbImport raw fetch() calls
- Removed AdminDashboard.jsx, replaced by RoadmapPage
- Added @radix-ui/react-collapsible + collapsible shadcn component
- Security audit by Private_Hudson: PASS (CSRF fix verified,
  admin endpoints gated, path traversal mitigated, XSS safe)
2026-05-11 21:42:36 -05:00
null 890427c75a v0.24.3: Session fixes, activity log corrections, UI polish 2026-05-11 13:39:48 -05:00
null 314159d241 v0.21.1: Loading Skeletons & Async State
- Reusable Skeleton component (line, circle, card, button, input variants)
- TrackerPage: skeleton cards, rows, buckets with aria-busy attributes
- BillsPage: skeleton rows during loading
- Bug fix: double closing brace />}} on Bucket component
- Hudson security audit: 5/5 PASS
2026-05-10 01:35:41 -05:00
null e184fed88a v0.20.7: Keyboard navigation and ARIA accessibility
- Skip-to-content link for keyboard users (sr-only/focus:not-sr-only pattern)
- aria-expanded and aria-haspopup on Tracker menu dropdown
- aria-label on footer, role='main' and aria-labelledby on layout wrapper
- Main content wrapped in <main> with unique id from React useId()
- Fixed build error: useId imported from react, not react-router-dom
- Hudson security audit: 5/5 PASS (no XSS, no DOM clobbering, no injection)
2026-05-10 00:18:36 -05:00
_null 969139251d calendar 2026-05-04 13:14:32 -05:00
_null b9d1366d46 initial commit 2026-05-03 19:51:57 -05:00