From 10b20b9d55e4c02f1a5dca5d104b1c233ccca8d6 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 6 Nov 2026 21:53:04 +0700 Subject: [PATCH] =?UTF-8?q?feat(web):=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B8=20=D1=82=D0=B5=D0=BC=D1=83=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=B0=D0=BB=D0=B8=D1=82=D1=80=D1=83=20=D0=B8=20?= =?UTF-8?q?=D1=88=D1=80=D0=B8=D1=84=D1=82=D1=8B=20Geist=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD=D0=B0=20VPS-Tracker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- apps/web/package.json | 2 + apps/web/src/main.tsx | 1 + apps/web/src/styles/theme.css | 112 ++++++++++++++++++++++++++++++++++ pnpm-lock.yaml | 16 +++++ 4 files changed, 131 insertions(+) create mode 100644 apps/web/src/styles/theme.css diff --git a/apps/web/package.json b/apps/web/package.json index 3576dc8..6d61bff 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,8 @@ "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@fontsource-variable/geist": "^5.3.0", + "@fontsource-variable/geist-mono": "^5.3.0", "@hookform/resolvers": "^3.10.0", "@tanstack/react-query": "^5.90.2", "@tanstack/react-query-devtools": "^5.90.2", diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx index 1f93d91..461d7e4 100644 --- a/apps/web/src/main.tsx +++ b/apps/web/src/main.tsx @@ -5,6 +5,7 @@ import { RouterProvider } from '@tanstack/react-router' import { Toaster } from '@cfdm/ui/components/sonner' import '@cfdm/ui/globals.css' +import '@/styles/theme.css' import { queryClient } from '@/lib/queryClient' import { createRouter } from '@/lib/router' diff --git a/apps/web/src/styles/theme.css b/apps/web/src/styles/theme.css new file mode 100644 index 0000000..0e50890 --- /dev/null +++ b/apps/web/src/styles/theme.css @@ -0,0 +1,112 @@ +/* + * VPS-Tracker theme layer (design canvas «VPS-Tracker», see docs/ui-migration-plan.md). + * Overrides tokens only — @cfdm/ui/globals.css stays shadcn CLI output, ReUI components are not restyled. + */ +@import '@fontsource-variable/geist'; +@import '@fontsource-variable/geist-mono'; + +:root { + --font-sans: 'Geist Variable', ui-sans-serif, system-ui, sans-serif; + --font-mono: 'Geist Mono Variable', ui-monospace, SFMono-Regular, monospace; + + --background: oklch(0.973 0.004 247.858); + --foreground: oklch(0.141 0.006 264); + --card: oklch(1 0 0); + --card-foreground: oklch(0.141 0.006 264); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.141 0.006 264); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.958 0.005 247.858); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.958 0.005 247.858); + --muted-foreground: oklch(0.52 0.01 264); + --accent: oklch(0.942 0.016 264.376); + --accent-foreground: oklch(0.205 0 0); + --border: oklch(0.904 0.006 264); + --input: oklch(0.904 0.006 264); + --ring: oklch(0.488 0.243 264.376); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.444 0.177 26.899); + --success: oklch(0.696 0.17 162.48); + --success-foreground: oklch(0.378 0.077 168.94); + --warning: oklch(0.795 0.184 86.047); + --warning-foreground: oklch(0.421 0.095 57.708); + --info: oklch(0.606 0.25 292.717); + --info-foreground: oklch(0.283 0.141 291.089); + --invert: oklch(0.21 0.006 285.885); + --invert-foreground: oklch(0.985 0 0); + --chart-1: oklch(0.546 0.215 264.376); + --chart-2: oklch(0.527 0.154 150.069); + --chart-3: oklch(0.625 0.162 41.5); + --chart-4: oklch(0.591 0.224 296.4); + + /* Sidebar stays dark in the light theme. */ + --sidebar: oklch(0.152 0.01 264.376); + --sidebar-foreground: oklch(0.92 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.24 0.012 264.376); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 8%); + --sidebar-ring: oklch(0.488 0.243 264.376); +} + +/* Dark-sidebar scope in light theme: inner text/border/muted tokens follow the sidebar. */ +:root:not(.dark) [data-slot='sidebar-inner'] { + --foreground: oklch(0.92 0 0); + --muted-foreground: oklch(0.648 0.008 264.376); + --border: oklch(1 0 0 / 8%); + --muted: oklch(0.24 0.012 264.376); + --background: oklch(0.133 0.011 264.376); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --card: oklch(0.191 0.011 264.376); + --input: oklch(1 0 0 / 15%); + --accent: oklch(0.24 0.012 264.376); + --accent-foreground: oklch(0.985 0 0); + color-scheme: dark; +} + +.dark { + --background: oklch(0.133 0.011 264.376); + --foreground: oklch(0.985 0 0); + --card: oklch(0.191 0.011 264.376); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.191 0.011 264.376); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.252 0.01 264.376); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.252 0.01 264.376); + --muted-foreground: oklch(0.648 0.008 264.376); + --accent: oklch(0.285 0.022 264.376); + --accent-foreground: oklch(0.985 0 0); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.488 0.243 264.376); + --destructive: oklch(0.704 0.191 22.216); + --destructive-foreground: oklch(0.577 0.245 27.325); + --success: oklch(0.696 0.17 162.48); + --success-foreground: oklch(0.596 0.145 163.225); + --warning: oklch(0.795 0.184 86.047); + --warning-foreground: oklch(0.681 0.162 75.834); + --info: oklch(0.606 0.25 292.717); + --info-foreground: oklch(0.541 0.281 293.009); + --invert: oklch(0.37 0.013 285.805); + --invert-foreground: oklch(0.985 0 0); + --chart-1: oklch(0.637 0.222 264.376); + --chart-2: oklch(0.696 0.17 151.328); + --chart-3: oklch(0.713 0.176 47.6); + --chart-4: oklch(0.714 0.173 303.9); + + --sidebar: oklch(0.191 0.011 264.376); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.262 0.014 264.376); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.488 0.243 264.376); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5f68d0..ec88a9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -114,6 +114,12 @@ importers: '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.2.7) + '@fontsource-variable/geist': + specifier: ^5.3.0 + version: 5.3.0 + '@fontsource-variable/geist-mono': + specifier: ^5.3.0 + version: 5.3.0 '@hookform/resolvers': specifier: ^3.10.0 version: 3.10.0(react-hook-form@7.80.0(react@19.2.7)) @@ -978,6 +984,12 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + '@fontsource-variable/geist-mono@5.3.0': + resolution: {integrity: sha512-vBbuwDEo9AkrqADMXOrlAR3DFcJi4/JxeuU43FoiQERnNwsfXNnvxvReZG02cQKmyk4DZkZdBZX3oTDvy2zBAw==} + + '@fontsource-variable/geist@5.3.0': + resolution: {integrity: sha512-j0m+vLQuG5XAYoHtGCVu0spvlGreR3EzpECUVzkFmI1mTVnAO38l/NEPDCFgZ177JxzYJCLSmTQibIiYPilGrA==} + '@hookform/resolvers@3.10.0': resolution: {integrity: sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==} peerDependencies: @@ -4145,6 +4157,10 @@ snapshots: '@floating-ui/utils@0.2.11': {} + '@fontsource-variable/geist-mono@5.3.0': {} + + '@fontsource-variable/geist@5.3.0': {} + '@hookform/resolvers@3.10.0(react-hook-form@7.80.0(react@19.2.7))': dependencies: react-hook-form: 7.80.0(react@19.2.7)