From ff1da2b2b85e72e30cc216c1f7a4a576b6a4438f Mon Sep 17 00:00:00 2001 From: trueberryless Date: Sun, 7 Jul 2024 19:15:06 +0200 Subject: [PATCH] themes; puh version-patch --- package.json | 1 + pnpm-lock.yaml | 29 +- src/app/test_data.json | 2 +- src/components/dashboard/dashboard.tsx | 20 +- src/components/navbar.tsx | 11 +- src/components/{ => themes}/mode-switch.tsx | 0 src/components/themes/theme-diamond.tsx | 116 +++++ .../{ => themes}/theme-provider.tsx | 0 src/components/themes/theme-switcher.tsx | 110 ++++ src/components/ui/skeleton.tsx | 15 + src/lib/chart-themes.ts | 484 ++++++++++++++++++ src/lib/charts.ts | 25 + src/pages/_app.tsx | 43 ++ src/styles/globals.css | 406 ++++++++++++++- 14 files changed, 1241 insertions(+), 21 deletions(-) rename src/components/{ => themes}/mode-switch.tsx (100%) create mode 100644 src/components/themes/theme-diamond.tsx rename src/components/{ => themes}/theme-provider.tsx (100%) create mode 100644 src/components/themes/theme-switcher.tsx create mode 100644 src/components/ui/skeleton.tsx create mode 100644 src/lib/chart-themes.ts create mode 100644 src/lib/charts.ts diff --git a/package.json b/package.json index 03d7581..4c59cfb 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "react-dom": "^18", "react-hook-form": "^7.52.1", "recharts": "^2.12.7", + "swr": "^2.2.5", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "zod": "^3.23.8" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8966bd..29001a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: recharts: specifier: ^2.12.7 version: 2.12.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + swr: + specifier: ^2.2.5 + version: 2.2.5(react@18.3.1) tailwind-merge: specifier: ^2.3.0 version: 2.3.0 @@ -2363,6 +2366,11 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + swr@2.2.5: + resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + tailwind-merge@2.3.0: resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==} @@ -2470,6 +2478,11 @@ packages: '@types/react': optional: true + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -3864,7 +3877,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.34.3(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -3888,7 +3901,7 @@ snapshots: enhanced-resolve: 5.17.0 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.14.0 @@ -3910,7 +3923,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -4958,6 +4971,12 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + swr@2.2.5(react@18.3.1): + dependencies: + client-only: 0.0.1 + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) + tailwind-merge@2.3.0: dependencies: '@babel/runtime': 7.24.7 @@ -5094,6 +5113,10 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 + use-sync-external-store@1.2.2(react@18.3.1): + dependencies: + react: 18.3.1 + util-deprecate@1.0.2: {} victory-vendor@36.9.2: diff --git a/src/app/test_data.json b/src/app/test_data.json index f349ce7..d3cd763 100644 --- a/src/app/test_data.json +++ b/src/app/test_data.json @@ -1,6 +1,6 @@ { "username": "trueberryless", - "lastExported": "2024-07-07T11:59:53.251Z", + "lastExported": "2024-07-05T11:59:53.251Z", "exportReminder": "monthly", "projects": [ { diff --git a/src/components/dashboard/dashboard.tsx b/src/components/dashboard/dashboard.tsx index 7fcefd8..7a7db40 100644 --- a/src/components/dashboard/dashboard.tsx +++ b/src/components/dashboard/dashboard.tsx @@ -116,17 +116,17 @@ export default function Dashboard() { return (
- {shouldShowExportNotification(user) && ( - - - Notification! - - We recommend exporting your data regularly. Head to Settings → Data - Management to export your data now. Stay safe! - - - )}
+ {shouldShowExportNotification(user) && ( + + + Notification! + + We recommend exporting your data regularly. Head to Settings → Data + Management to export your data now. Stay safe! + + + )}

Dashboard

diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index af5b8f6..3eb1351 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -19,8 +19,12 @@ import { } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; -import ModeToggle from "./mode-switch"; +import ModeToggle from "./themes/mode-switch"; import { useUser } from "./UserContext"; +import ThemeSwitcher from "./themes/theme-switcher"; +import { getChartThemes } from "@/lib/chart-themes"; + +const chartThemes = getChartThemes(); export default function Navbar() { const { user, setUser } = useUser(); @@ -185,9 +189,12 @@ export default function Navbar() {
+
+ +
-
+
{user.username}
+
+ + handleThemeChange("default")}> +
+ +
Default
+
+
+ handleThemeChange("palette")}> +
+ +
Palette
+
+
+ handleThemeChange("sapphire")}> +
+ +
Sapphire
+
+
+ handleThemeChange("ruby")}> +
+ +
Ruby
+
+
+ handleThemeChange("emerald")}> +
+ +
Emerald
+
+
+ handleThemeChange("daylight")}> +
+ +
Daylight
+
+
+ handleThemeChange("midnight")}> +
+ +
Midnight
+
+
+
+
+ ); +} diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx new file mode 100644 index 0000000..01b8b6d --- /dev/null +++ b/src/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/src/lib/chart-themes.ts b/src/lib/chart-themes.ts new file mode 100644 index 0000000..d9cabfe --- /dev/null +++ b/src/lib/chart-themes.ts @@ -0,0 +1,484 @@ +import { themeColorsToCssVariables } from "@/lib/charts"; + +export const CHART_THEMES = [ + { + name: "Default", + id: "default-shadcn", + colors: { + background: "0 0% 100%", + foreground: "240 10% 3.9%", + card: "0 0% 100%", + "card-foreground": "240 10% 3.9%", + popover: "0 0% 100%", + "popover-foreground": "240 10% 3.9%", + primary: "240 5.9% 10%", + "primary-foreground": "0 0% 98%", + secondary: "240 4.8% 95.9%", + "secondary-foreground": "240 5.9% 10%", + muted: "240 4.8% 95.9%", + "muted-foreground": "240 3.8% 46.1%", + accent: "240 4.8% 95.9%", + "accent-foreground": "240 5.9% 10%", + destructive: "0 84.2% 60.2%", + "destructive-foreground": "0 0% 98%", + border: "240 5.9% 90%", + input: "240 5.9% 90%", + ring: "240 10% 3.9%", + "chart-1": "173 58% 39%", + "chart-2": "12 76% 61%", + "chart-3": "197 37% 24%", + "chart-4": "43 74% 66%", + "chart-5": "27 87% 67%", + }, + colorsDark: { + background: "240 10% 3.9%", + foreground: "0 0% 98%", + card: "240 10% 3.9%", + "card-foreground": "0 0% 98%", + popover: "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + primary: "0 0% 98%", + "primary-foreground": "240 5.9% 10%", + secondary: "240 3.7% 15.9%", + "secondary-foreground": "0 0% 98%", + muted: "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + accent: "240 3.7% 15.9%", + "accent-foreground": "0 0% 98%", + destructive: "0 62.8% 30.6%", + "destructive-foreground": "0 0% 98%", + border: "240 3.7% 15.9%", + input: "240 3.7% 15.9%", + ring: "240 4.9% 83.9%", + "chart-1": "220 70% 50%", + "chart-5": "160 60% 45%", + "chart-3": "30 80% 55%", + "chart-4": "280 65% 60%", + "chart-2": "340 75% 55%", + }, + fontFamily: { + heading: { + name: "Inter", + type: "sans-serif", + }, + body: { + name: "Inter", + type: "sans-serif", + }, + }, + radius: 0.5, + }, + { + name: "Palette", + id: "default-palette", + colors: { + background: "0 0% 100%", + foreground: "240 10% 3.9%", + card: "0 0% 100%", + "card-foreground": "240 10% 3.9%", + popover: "0 0% 100%", + "popover-foreground": "240 10% 3.9%", + primary: "240 5.9% 10%", + "primary-foreground": "0 0% 98%", + secondary: "240 4.8% 95.9%", + "secondary-foreground": "240 5.9% 10%", + muted: "240 4.8% 95.9%", + "muted-foreground": "240 3.8% 46.1%", + accent: "240 4.8% 95.9%", + "accent-foreground": "240 5.9% 10%", + destructive: "0 84.2% 60.2%", + "destructive-foreground": "0 0% 98%", + border: "240 5.9% 90%", + input: "240 5.9% 90%", + ring: "240 10% 3.9%", + "chart-1": "12 76% 61%", + "chart-2": "173 58% 39%", + "chart-3": "197 37% 24%", + "chart-4": "43 74% 66%", + "chart-5": "27 87% 67%", + }, + colorsDark: { + background: "240 10% 3.9%", + foreground: "0 0% 98%", + card: "240 10% 3.9%", + "card-foreground": "0 0% 98%", + popover: "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + primary: "0 0% 98%", + "primary-foreground": "240 5.9% 10%", + secondary: "240 3.7% 15.9%", + "secondary-foreground": "0 0% 98%", + muted: "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + accent: "240 3.7% 15.9%", + "accent-foreground": "0 0% 98%", + destructive: "0 62.8% 30.6%", + "destructive-foreground": "0 0% 98%", + border: "240 3.7% 15.9%", + input: "240 3.7% 15.9%", + ring: "240 4.9% 83.9%", + "chart-1": "220 70% 50%", + "chart-2": "160 60% 45%", + "chart-3": "30 80% 55%", + "chart-4": "280 65% 60%", + "chart-5": "340 75% 55%", + }, + fontFamily: { + heading: { + name: "Inter", + type: "sans-serif", + }, + body: { + name: "Inter", + type: "sans-serif", + }, + }, + radius: 0.5, + }, + { + name: "Sapphire", + id: "default-sapphire", + colors: { + background: "0 0% 100%", + foreground: "222.2 84% 4.9%", + card: "0 0% 100%", + cardForeground: "222.2 84% 4.9%", + popover: "0 0% 100%", + popoverForeground: "222.2 84% 4.9%", + primary: "221.2 83.2% 53.3%", + primaryForeground: "210 40% 98%", + secondary: "210 40% 96.1%", + secondaryForeground: "222.2 47.4% 11.2%", + muted: "210 40% 96.1%", + mutedForeground: "215.4 16.3% 44%", + accent: "210 40% 96.1%", + accentForeground: "222.2 47.4% 11.2%", + destructive: "0 72% 51%", + destructiveForeground: "210 40% 98%", + border: "214.3 31.8% 91.4%", + input: "214.3 31.8% 91.4%", + ring: "221.2 83.2% 53.3%", + "chart-1": "221.2 83.2% 53.3%", + "chart-2": "212 95% 68%", + "chart-3": "216 92% 60%", + "chart-4": "210 98% 78%", + "chart-5": "212 97% 87%", + }, + colorsDark: { + background: "240 10% 3.9%", + foreground: "0 0% 98%", + card: "240 10% 3.9%", + "card-foreground": "0 0% 98%", + popover: "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + primary: "221.2 83.2% 53.3%", + primaryForeground: "210 40% 98%", + secondary: "210 40% 96.1%", + secondaryForeground: "222.2 47.4% 11.2%", + muted: "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + accent: "210 40% 96.1%", + accentForeground: "222.2 47.4% 11.2%", + destructive: "0 72% 51%", + destructiveForeground: "210 40% 98%", + border: "240 3.7% 15.9%", + input: "240 3.7% 15.9%", + ring: "221.2 83.2% 53.3%", + "chart-1": "221.2 83.2% 53.3%", + "chart-2": "212 95% 68%", + "chart-3": "216 92% 60%", + "chart-4": "210 98% 78%", + "chart-5": "212 97% 87%", + }, + fontFamily: { + heading: { + name: "Inter", + type: "sans-serif", + }, + body: { + name: "Inter", + type: "sans-serif", + }, + }, + radius: 0.5, + }, + { + name: "Ruby", + id: "default-ruby", + colors: { + background: "0 0% 100%", + foreground: "240 10% 3.9%", + card: "0 0% 100%", + cardForeground: "240 10% 3.9%", + popover: "0 0% 100%", + popoverForeground: "240 10% 3.9%", + primary: "346.8 77.2% 49.8%", + primaryForeground: "355.7 100% 99%", + secondary: "240 4.8% 95.9%", + secondaryForeground: "240 5.9% 10%", + muted: "240 4.8% 95.9%", + mutedForeground: "240 3.8% 45%", + accent: "240 4.8% 95.9%", + accentForeground: "240 5.9% 10%", + destructive: "0 72% 51%", + destructiveForeground: "0 0% 98%", + border: "240 5.9% 90%", + input: "240 5.9% 90%", + ring: "346.8 77.2% 49.8%", + "chart-1": "347 77% 50%", + "chart-2": "352 83% 91%", + "chart-3": "350 80% 72%", + "chart-4": "351 83% 82%", + "chart-5": "349 77% 62%", + }, + colorsDark: { + background: "240 10% 3.9%", + foreground: "0 0% 98%", + card: "240 10% 3.9%", + "card-foreground": "0 0% 98%", + popover: "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + primary: "346.8 77.2% 49.8%", + primaryForeground: "355.7 100% 99%", + secondary: "240 4.8% 95.9%", + secondaryForeground: "240 5.9% 10%", + muted: "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + accent: "240 4.8% 95.9%", + accentForeground: "240 5.9% 10%", + destructive: "0 72% 51%", + destructiveForeground: "0 0% 98%", + border: "240 3.7% 15.9%", + input: "240 3.7% 15.9%", + ring: "221.2 83.2% 53.3%", + "chart-1": "347 77% 50%", + "chart-2": "349 77% 62%", + "chart-3": "350 80% 72%", + "chart-4": "351 83% 82%", + "chart-5": "352 83% 91%", + }, + fontFamily: { + heading: { + name: "Inter", + type: "sans-serif", + }, + body: { + name: "Inter", + type: "sans-serif", + }, + }, + radius: 0.5, + }, + { + name: "Emerald", + id: "default-emerald", + colors: { + background: "0 0% 100%", + foreground: "240 10% 3.9%", + card: "0 0% 100%", + cardForeground: "240 10% 3.9%", + popover: "0 0% 100%", + popoverForeground: "240 10% 3.9%", + primary: "142 86% 28%", + primaryForeground: "356 29% 98%", + secondary: "240 4.8% 95.9%", + secondaryForeground: "240 5.9% 10%", + muted: "240 4.8% 95.9%", + mutedForeground: "240 3.8% 45%", + accent: "240 4.8% 95.9%", + accentForeground: "240 5.9% 10%", + destructive: "0 72% 51%", + destructiveForeground: "0 0% 98%", + border: "240 5.9% 90%", + input: "240 5.9% 90%", + ring: "142 86% 28%", + "chart-1": "139 65% 20%", + "chart-2": "140 74% 44%", + "chart-3": "142 88% 28%", + "chart-4": "137 55% 15%", + "chart-5": "141 40% 9%", + }, + colorsDark: { + background: "240 10% 3.9%", + foreground: "0 0% 98%", + card: "240 10% 3.9%", + "card-foreground": "0 0% 98%", + popover: "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + primary: "142 86% 28%", + primaryForeground: "356 29% 98%", + secondary: "240 4.8% 95.9%", + secondaryForeground: "240 5.9% 10%", + muted: "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + accent: "240 4.8% 95.9%", + accentForeground: "240 5.9% 10%", + destructive: "0 72% 51%", + destructiveForeground: "0 0% 98%", + border: "240 3.7% 15.9%", + input: "240 3.7% 15.9%", + ring: "142 86% 28%", + "chart-1": "142 88% 28%", + "chart-2": "139 65% 20%", + "chart-3": "140 74% 24%", + "chart-4": "137 55% 15%", + "chart-5": "141 40% 9%", + }, + fontFamily: { + heading: { + name: "Inter", + type: "sans-serif", + }, + body: { + name: "Inter", + type: "sans-serif", + }, + }, + radius: 0.5, + }, + { + name: "Daylight", + id: "default-daylight", + colors: { + background: "36 39% 88%", + foreground: "36 45% 15%", + primary: "36 45% 70%", + primaryForeground: "36 45% 11%", + secondary: "40 35% 77%", + secondaryForeground: "36 45% 25%", + accent: "36 64% 57%", + accentForeground: "36 72% 17%", + destructive: "0 84% 37%", + destructiveForeground: "0 0% 98%", + muted: "36 33% 75%", + mutedForeground: "36 45% 25%", + card: "36 46% 82%", + cardForeground: "36 45% 20%", + popover: "0 0% 100%", + popoverForeground: "240 10% 3.9%", + border: "36 45% 60%", + input: "36 45% 60%", + ring: "36 45% 30%", + "chart-1": "25 34% 28%", + "chart-2": "26 36% 34%", + "chart-3": "28 40% 40%", + "chart-4": "31 41% 48%", + "chart-5": "35 43% 53%", + }, + colorsDark: { + background: "36 39% 88%", + foreground: "36 45% 15%", + primary: "36 45% 70%", + primaryForeground: "36 45% 11%", + secondary: "40 35% 77%", + secondaryForeground: "36 45% 25%", + accent: "36 64% 57%", + accentForeground: "36 72% 17%", + destructive: "0 84% 37%", + destructiveForeground: "0 0% 98%", + muted: "36 33% 75%", + mutedForeground: "36 45% 25%", + card: "36 46% 82%", + cardForeground: "36 45% 20%", + popover: "0 0% 100%", + popoverForeground: "240 10% 3.9%", + border: "36 45% 60%", + input: "36 45% 60%", + ring: "36 45% 30%", + "chart-1": "25 34% 28%", + "chart-2": "26 36% 34%", + "chart-3": "28 40% 40%", + "chart-4": "31 41% 48%", + "chart-5": "35 43% 53%", + }, + fontFamily: { + heading: { + name: "DM Sans", + type: "sans-serif", + }, + body: { + name: "Space Mono", + type: "monospace", + }, + }, + }, + { + name: "Midnight", + id: "default-midnight", + colors: { + background: "240 5% 6%", + foreground: "60 5% 90%", + primary: "240 0% 90%", + primaryForeground: "60 0% 0%", + secondary: "240 4% 15%", + secondaryForeground: "60 5% 85%", + accent: "240 0% 13%", + accentForeground: "60 0% 100%", + destructive: "0 60% 50%", + destructiveForeground: "0 0% 98%", + muted: "240 5% 25%", + mutedForeground: "60 5% 85%", + card: "240 4% 10%", + cardForeground: "60 5% 90%", + popover: "240 5% 15%", + popoverForeground: "60 5% 85%", + border: "240 6% 20%", + input: "240 6% 20%", + ring: "240 5% 90%", + "chart-1": "359 2% 90%", + "chart-2": "240 1% 74%", + "chart-3": "240 1% 58%", + "chart-4": "240 1% 42%", + "chart-5": "240 2% 26%", + }, + colorsDark: { + background: "240 5% 6%", + foreground: "60 5% 90%", + primary: "240 0% 90%", + primaryForeground: "60 0% 0%", + secondary: "240 4% 15%", + secondaryForeground: "60 5% 85%", + accent: "240 0% 13%", + accentForeground: "60 0% 100%", + destructive: "0 60% 50%", + destructiveForeground: "0 0% 98%", + muted: "240 5% 25%", + mutedForeground: "60 5% 85%", + card: "240 4% 10%", + cardForeground: "60 5% 90%", + popover: "240 5% 15%", + popoverForeground: "60 5% 85%", + border: "240 6% 20%", + input: "240 6% 20%", + ring: "240 5% 90%", + "chart-1": "359 2% 90%", + "chart-2": "240 1% 74%", + "chart-3": "240 1% 58%", + "chart-4": "240 1% 42%", + "chart-5": "240 2% 26%", + }, + fontFamily: { + heading: { + name: "Manrope", + type: "sans-serif", + }, + body: { + name: "Manrope", + type: "sans-serif", + }, + }, + radius: 0.5, + }, +] as const; + +export type ChartTheme = ReturnType[number]; + +export function getChartThemes() { + return CHART_THEMES.map((theme) => ({ + ...theme, + cssVars: { + light: themeColorsToCssVariables(theme.colors), + dark: themeColorsToCssVariables(theme.colorsDark), + }, + })); +} diff --git a/src/lib/charts.ts b/src/lib/charts.ts new file mode 100644 index 0000000..d691cf7 --- /dev/null +++ b/src/lib/charts.ts @@ -0,0 +1,25 @@ +export function themeColorsToCssVariables( + colors: Record +): Record { + const cssVars = colors + ? Object.fromEntries( + Object.entries(colors).map(([name, value]) => { + if (value === undefined) return [] + const cssName = themeColorNameToCssVariable(name) + return [cssName, value] + }) + ) + : {} + + // for (const key of Array.from({ length: 5 }, (_, index) => index)) { + // cssVars[`--chart-${key + 1}`] = + // cssVars[`--chart-${key + 1}`] || + // `${cssVars["--primary"]} / ${100 - key * 20}%` + // } + + return cssVars +} + +export function themeColorNameToCssVariable(name: string) { + return `--${name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}` +} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 57ebf8d..a41e88e 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -9,8 +9,10 @@ import { SignUp } from "@/components/sign-up"; import { ThemeProvider } from "next-themes"; import { Toaster } from "@/components/ui/toaster"; import { UserProvider, useUser } from "@/components/UserContext"; +import { CHART_THEMES, getChartThemes } from "@/lib/chart-themes"; const inter = Inter({ subsets: ["latin"] }); +const chartThemes = getChartThemes(); interface MyAppProps { Component: React.ElementType; @@ -20,6 +22,47 @@ interface MyAppProps { export default function MyApp({ Component, pageProps }: MyAppProps) { const { user, setUser } = useUser(); + function generateCssVariables(themes: any) { + let cssVariables = `:root {\n`; + + themes.forEach((theme: any) => { + // Object.entries(theme.colors).forEach(([key, value]) => { + // const variableName = `--${key}`; + // cssVariables += ` ${variableName}: ${value};\n`; + // }); + + // Object.entries(theme.colorsDark).forEach(([key, value]) => { + // const variableName = `--${key}-dark`; + // cssVariables += ` ${variableName}: ${value};\n`; + // }); + Object.entries(theme.colors).forEach(([key, value]) => { + if (key.includes("chart")) { + const variableName = `--${key.replace( + "chart", + "color" + )}-${theme.name.toLowerCase()}`; + cssVariables += ` ${variableName}: hsl(${value});\n`; + } + }); + Object.entries(theme.colorsDark).forEach(([key, value]) => { + if (key.includes("chart")) { + const variableName = `--${key.replace( + "chart", + "color" + )}-${theme.name.toLowerCase()}`; + cssVariables += ` ${variableName}-dark: hsl(${value});\n`; + } + }); + }); + + cssVariables += `}`; + + return cssVariables; + } + + const cssSelectors = generateCssVariables(CHART_THEMES); + console.log(cssSelectors); + useEffect(() => { const data = loadData(); if (data) { diff --git a/src/styles/globals.css b/src/styles/globals.css index 1c3f4f7..0c469a9 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -34,11 +34,53 @@ --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; + --chart-1: 222.2 84% 4.9%; + --chart-2: 222.2 47.4% 11.2%; + --chart-3: 217.2 32.6% 17.5%; + --chart-4: 217.2 26.8% 23.5%; + --chart-5: 206.2 13.8% 32.5%; + + --color-1: hsl(var(--chart-1)); + --color-2: hsl(var(--chart-2)); + --color-3: hsl(var(--chart-3)); + --color-4: hsl(var(--chart-4)); + --color-5: hsl(var(--chart-5)); + + --color-1-default: hsl(222.2 84% 4.9%); + --color-2-default: hsl(222.2 47.4% 11.2%); + --color-3-default: hsl(217.2 32.6% 17.5%); + --color-4-default: hsl(217.2 26.8% 23.5%); + --color-5-default: hsl(206.2 13.8% 32.5%); + --color-1-palette: hsl(12 76% 61%); + --color-2-palette: hsl(173 58% 39%); + --color-3-palette: hsl(197 37% 24%); + --color-4-palette: hsl(43 74% 66%); + --color-5-palette: hsl(27 87% 67%); + --color-1-sapphire: hsl(221.2 83.2% 53.3%); + --color-2-sapphire: hsl(212 95% 68%); + --color-3-sapphire: hsl(216 92% 60%); + --color-4-sapphire: hsl(210 98% 78%); + --color-5-sapphire: hsl(212 97% 87%); + --color-1-ruby: hsl(347 77% 50%); + --color-2-ruby: hsl(352 83% 91%); + --color-3-ruby: hsl(350 80% 72%); + --color-4-ruby: hsl(351 83% 82%); + --color-5-ruby: hsl(349 77% 62%); + --color-1-emerald: hsl(139 65% 20%); + --color-2-emerald: hsl(140 74% 44%); + --color-3-emerald: hsl(142 88% 28%); + --color-4-emerald: hsl(137 55% 15%); + --color-5-emerald: hsl(141 40% 9%); + --color-1-daylight: hsl(25 34% 28%); + --color-2-daylight: hsl(26 36% 34%); + --color-3-daylight: hsl(28 40% 40%); + --color-4-daylight: hsl(31 41% 48%); + --color-5-daylight: hsl(35 43% 53%); + --color-1-midnight: hsl(359 2% 90%); + --color-2-midnight: hsl(240 1% 74%); + --color-3-midnight: hsl(240 1% 58%); + --color-4-midnight: hsl(240 1% 42%); + --color-5-midnight: hsl(240 2% 26%); } .dark { @@ -70,12 +112,366 @@ --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; + --chart-1: 210 40% 98%; + --chart-2: 212.7 26.8% 83.9%; + --chart-3: 215 20.2% 65.1%; + --chart-4: 220.6 13.2% 59.1%; + --chart-5: 224.8 9.5% 51.3%; + + --color-1-default: hsl(210 40% 98%); + --color-2-default: hsl(212.7 26.8% 83.9%); + --color-3-default: hsl(215 20.2% 65.1%); + --color-4-default: hsl(220.6 13.2% 59.1%); + --color-5-default: hsl(224.8 9.5% 51.3%); + --color-1-palette: hsl(220 70% 50%); + --color-2-palette: hsl(160 60% 45%); + --color-3-palette: hsl(30 80% 55%); + --color-4-palette: hsl(280 65% 60%); + --color-5-palette: hsl(340 75% 55%); + --color-1-sapphire: hsl(221.2 83.2% 53.3%); + --color-2-sapphire: hsl(212 95% 68%); + --color-3-sapphire: hsl(216 92% 60%); + --color-4-sapphire: hsl(210 98% 78%); + --color-5-sapphire: hsl(212 97% 87%); + --color-1-ruby: hsl(347 77% 50%); + --color-2-ruby: hsl(349 77% 62%); + --color-3-ruby: hsl(350 80% 72%); + --color-4-ruby: hsl(351 83% 82%); + --color-5-ruby: hsl(352 83% 91%); + --color-1-emerald: hsl(142 88% 28%); + --color-2-emerald: hsl(139 65% 20%); + --color-3-emerald: hsl(140 74% 24%); + --color-4-emerald: hsl(137 55% 15%); + --color-5-emerald: hsl(141 40% 9%); + --color-1-daylight: hsl(25 34% 28%); + --color-2-daylight: hsl(26 36% 34%); + --color-3-daylight: hsl(28 40% 40%); + --color-4-daylight: hsl(31 41% 48%); + --color-5-daylight: hsl(35 43% 53%); + --color-1-midnight: hsl(359 2% 90%); + --color-2-midnight: hsl(240 1% 74%); + --color-3-midnight: hsl(240 1% 58%); + --color-4-midnight: hsl(240 1% 42%); + --color-5-midnight: hsl(240 2% 26%); + } + + .palette { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 10% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } + .palette.dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; --chart-1: 220 70% 50%; --chart-2: 160 60% 45%; --chart-3: 30 80% 55%; --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; } + + .sapphire { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 221.2 83.2% 53.3%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 44%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 72% 51%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 221.2 83.2% 53.3%; + --chart-1: 221.2 83.2% 53.3%; + --chart-2: 212 95% 68%; + --chart-3: 216 92% 60%; + --chart-4: 210 98% 78%; + --chart-5: 212 97% 87%; + } + .sapphire.dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 221.2 83.2% 53.3%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 72% 51%; + --destructive-foreground: 210 40% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 221.2 83.2% 53.3%; + --chart-1: 221.2 83.2% 53.3%; + --chart-2: 212 95% 68%; + --chart-3: 216 92% 60%; + --chart-4: 210 98% 78%; + --chart-5: 212 97% 87%; + } + + .ruby { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 99%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 45%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 346.8 77.2% 49.8%; + --chart-1: 347 77% 50%; + --chart-2: 352 83% 91%; + --chart-3: 350 80% 72%; + --chart-4: 351 83% 82%; + --chart-5: 349 77% 62%; + } + .ruby.dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 99%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 221.2 83.2% 53.3%; + --chart-1: 347 77% 50%; + --chart-2: 349 77% 62%; + --chart-3: 350 80% 72%; + --chart-4: 351 83% 82%; + --chart-5: 352 83% 91%; + } + + .emerald { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 142 86% 28%; + --primary-foreground: 356 29% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 45%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 142 86% 28%; + --chart-1: 139 65% 20%; + --chart-2: 140 74% 44%; + --chart-3: 142 88% 28%; + --chart-4: 137 55% 15%; + --chart-5: 141 40% 9%; + } + .emerald.dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 142 86% 28%; + --primary-foreground: 356 29% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 142 86% 28%; + --chart-1: 142 88% 28%; + --chart-2: 139 65% 20%; + --chart-3: 140 74% 24%; + --chart-4: 137 55% 15%; + --chart-5: 141 40% 9%; + } + + .daylight { + --background: 36 39% 88%; + --foreground: 36 45% 15%; + --primary: 36 45% 70%; + --primary-foreground: 36 45% 11%; + --secondary: 40 35% 77%; + --secondary-foreground: 36 45% 25%; + --accent: 36 64% 57%; + --accent-foreground: 36 72% 17%; + --destructive: 0 84% 37%; + --destructive-foreground: 0 0% 98%; + --muted: 36 33% 75%; + --muted-foreground: 36 45% 25%; + --card: 36 46% 82%; + --card-foreground: 36 45% 20%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --border: 36 45% 60%; + --input: 36 45% 60%; + --ring: 36 45% 30%; + --chart-1: 25 34% 28%; + --chart-2: 26 36% 34%; + --chart-3: 28 40% 40%; + --chart-4: 31 41% 48%; + --chart-5: 35 43% 53%; + } + .daylight.dark { + --background: 36 39% 12%; + --foreground: 36 45% 90%; + --primary: 36 45% 85%; + --primary-foreground: 36 45% 30%; + --secondary: 40 35% 25%; + --secondary-foreground: 36 45% 70%; + --accent: 36 64% 40%; + --accent-foreground: 36 72% 85%; + --destructive: 0 84% 20%; + --destructive-foreground: 36 45% 85%; + --muted: 36 33% 30%; + --muted-foreground: 36 45% 70%; + --card: 36 46% 18%; + --card-foreground: 36 45% 80%; + --popover: 0 0% 5%; + --popover-foreground: 240 10% 98%; + --border: 36 45% 40%; + --input: 36 45% 40%; + --ring: 36 45% 70%; + --chart-1: 25 34% 60%; + --chart-2: 26 36% 55%; + --chart-3: 28 40% 50%; + --chart-4: 31 41% 45%; + --chart-5: 35 43% 40%; + } + + .midnight { + --background: 240 5% 95%; + --foreground: 60 5% 10%; + --primary: 240 0% 10%; + --primary-foreground: 60 0% 95%; + --secondary: 240 4% 85%; + --secondary-foreground: 60 5% 15%; + --accent: 240 0% 35%; + --accent-foreground: 60 0% 0%; + --destructive: 0 60% 80%; + --destructive-foreground: 0 0% 20%; + --muted: 240 5% 75%; + --muted-foreground: 60 5% 15%; + --card: 240 4% 85%; + --card-foreground: 60 5% 10%; + --popover: 240 5% 85%; + --popover-foreground: 60 5% 15%; + --border: 240 6% 80%; + --input: 240 6% 80%; + --ring: 240 5% 10%; + --chart-1: 359 2% 10%; + --chart-2: 240 1% 26%; + --chart-3: 240 1% 42%; + --chart-4: 240 1% 58%; + --chart-5: 240 2% 74%; + } + .midnight.dark { + --background: 240 5% 6%; + --foreground: 60 5% 90%; + --primary: 240 0% 90%; + --primary-foreground: 60 0% 0%; + --secondary: 240 4% 15%; + --secondary-foreground: 60 5% 85%; + --accent: 240 0% 13%; + --accent-foreground: 60 0% 100%; + --destructive: 0 60% 50%; + --destructive-foreground: 0 0% 98%; + --muted: 240 5% 25%; + --muted-foreground: 60 5% 85%; + --card: 240 4% 10%; + --card-foreground: 60 5% 90%; + --popover: 240 5% 15%; + --popover-foreground: 60 5% 85%; + --border: 240 6% 20%; + --input: 240 6% 20%; + --ring: 240 5% 90%; + --chart-1: 359 2% 90%; + --chart-2: 240 1% 74%; + --chart-3: 240 1% 58%; + --chart-4: 240 1% 42%; + --chart-5: 240 2% 26%; + } } @layer base {