From f7fb6910b675030fdb1d805df682919ff90bb6f6 Mon Sep 17 00:00:00 2001 From: Le-King-Fu Date: Fri, 13 Feb 2026 12:28:11 +0000 Subject: [PATCH] feat: add dark mode with famille-website-inspired warm gray palette Toggle via Moon/Sun button in sidebar. Persists to localStorage with prefers-color-scheme fallback. Fixes hardcoded colors (error banners, badges, chart tooltips, Settings text) to use CSS variables. Co-Authored-By: Claude Opus 4.6 --- src/components/dashboard/CategoryPieChart.tsx | 8 ++++ src/components/import/DuplicateCheckPanel.tsx | 4 +- src/components/import/ImportConfirmation.tsx | 2 +- src/components/import/SourceCard.tsx | 2 +- src/components/layout/Sidebar.tsx | 13 +++++- src/components/reports/CategoryBarChart.tsx | 3 ++ .../reports/CategoryOverTimeChart.tsx | 3 ++ src/components/reports/MonthlyTrendsChart.tsx | 3 ++ src/hooks/useTheme.ts | 42 +++++++++++++++++++ src/i18n/locales/en.json | 4 +- src/i18n/locales/fr.json | 4 +- src/pages/BudgetPage.tsx | 2 +- src/pages/ReportsPage.tsx | 2 +- src/pages/SettingsPage.tsx | 14 +++---- src/styles.css | 37 ++++++++++------ 15 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 src/hooks/useTheme.ts diff --git a/src/components/dashboard/CategoryPieChart.tsx b/src/components/dashboard/CategoryPieChart.tsx index e7cf7ee..5283c80 100644 --- a/src/components/dashboard/CategoryPieChart.tsx +++ b/src/components/dashboard/CategoryPieChart.tsx @@ -43,6 +43,14 @@ export default function CategoryPieChart({ data }: CategoryPieChartProps) { formatter={(value) => new Intl.NumberFormat("en-CA", { style: "currency", currency: "CAD" }).format(Number(value)) } + contentStyle={{ + backgroundColor: "var(--card)", + border: "1px solid var(--border)", + borderRadius: "8px", + color: "var(--foreground)", + }} + labelStyle={{ color: "var(--foreground)" }} + itemStyle={{ color: "var(--foreground)" }} /> diff --git a/src/components/import/DuplicateCheckPanel.tsx b/src/components/import/DuplicateCheckPanel.tsx index c2d57b4..15942be 100644 --- a/src/components/import/DuplicateCheckPanel.tsx +++ b/src/components/import/DuplicateCheckPanel.tsx @@ -151,8 +151,8 @@ export default function DuplicateCheckPanel({ {isBatch diff --git a/src/components/import/ImportConfirmation.tsx b/src/components/import/ImportConfirmation.tsx index 8e763ca..3c9aa88 100644 --- a/src/components/import/ImportConfirmation.tsx +++ b/src/components/import/ImportConfirmation.tsx @@ -78,7 +78,7 @@ export default function ImportConfirmation({ {/* Rows to import */}
- +

{t("import.confirm.rowsToImport")} diff --git a/src/components/import/SourceCard.tsx b/src/components/import/SourceCard.tsx index cd28b8a..cf0114f 100644 --- a/src/components/import/SourceCard.tsx +++ b/src/components/import/SourceCard.tsx @@ -38,7 +38,7 @@ export default function SourceCard({ {isConfigured && ( )}

diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 73d6d60..dc99a36 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -10,8 +10,11 @@ import { BarChart3, Settings, Languages, + Moon, + Sun, } from "lucide-react"; import { NAV_ITEMS, APP_NAME } from "../../shared/constants"; +import { useTheme } from "../../hooks/useTheme"; const iconMap: Record> = { LayoutDashboard, @@ -26,6 +29,7 @@ const iconMap: Record> = { export default function Sidebar() { const { t, i18n } = useTranslation(); + const { theme, toggleTheme } = useTheme(); const toggleLanguage = () => { const next = i18n.language === "fr" ? "en" : "fr"; @@ -60,7 +64,14 @@ export default function Sidebar() { })} -
+
+
{error && ( -
+
{error}
)} diff --git a/src/pages/ReportsPage.tsx b/src/pages/ReportsPage.tsx index 05d0226..3383ed4 100644 --- a/src/pages/ReportsPage.tsx +++ b/src/pages/ReportsPage.tsx @@ -40,7 +40,7 @@ export default function ReportsPage() {
{state.error && ( -
+
{state.error}
)} diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index fc2c89e..6a89641 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -45,7 +45,7 @@ export default function SettingsPage() {

{APP_NAME}

-

+

{t("settings.version", { version })}

@@ -72,7 +72,7 @@ export default function SettingsPage() { {/* checking */} {state.status === "checking" && ( -
+
{t("settings.updates.checking")}
@@ -87,7 +87,7 @@ export default function SettingsPage() {
@@ -113,7 +113,7 @@ export default function SettingsPage() { {/* downloading */} {state.status === "downloading" && (
-
+
{t("settings.updates.downloading")} {progressPercent !== null && {progressPercent}%} @@ -145,7 +145,7 @@ export default function SettingsPage() { {/* installing */} {state.status === "installing" && ( -
+
{t("settings.updates.installing")}
@@ -158,7 +158,7 @@ export default function SettingsPage() { {t("settings.updates.error")}
-

{state.error}

+

{state.error}