From 3e61019b7f2bd0e94fb2ba227879345a5efb2b97 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 27 Feb 2026 21:49:14 +0100 Subject: [PATCH] Theme and default functionality --- src/app/globals.css | 151 +++++++++++++++----------- src/app/workspace/page.tsx | 26 ++++- src/components/sidebar/AppSidebar.tsx | 4 +- src/components/sidebar/Entity.tsx | 6 +- src/lib/types.ts | 5 + 5 files changed, 121 insertions(+), 71 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 10dc118..ce37d1c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -46,72 +46,99 @@ } :root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); + --radius: 0.75rem; + + --background: oklch(0.97 0.01 240); + --foreground: oklch(0.22 0.02 240); + + --card: oklch(0.99 0.005 240); + --card-foreground: oklch(0.22 0.02 240); + --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + --popover-foreground: oklch(0.22 0.02 240); + + /* Primary = architectural blue */ + --primary: oklch(0.55 0.16 250); + --primary-foreground: oklch(0.98 0.01 250); + + --secondary: oklch(0.93 0.02 240); + --secondary-foreground: oklch(0.28 0.02 240); + + --muted: oklch(0.94 0.015 240); + --muted-foreground: oklch(0.55 0.02 240); + + /* Accent = subtle violet for graph highlights */ + --accent: oklch(0.92 0.03 270); + --accent-foreground: oklch(0.30 0.04 270); + + --destructive: oklch(0.62 0.22 25); + + --border: oklch(0.90 0.015 240); + --input: oklch(0.90 0.015 240); + --ring: oklch(0.55 0.16 250); + + /* Charts (clean + modern) */ + --chart-1: oklch(0.55 0.16 250); + --chart-2: oklch(0.60 0.14 200); + --chart-3: oklch(0.62 0.18 280); + --chart-4: oklch(0.70 0.15 140); + --chart-5: oklch(0.65 0.20 30); + + --sidebar: oklch(0.95 0.01 240); + --sidebar-foreground: oklch(0.25 0.02 240); + --sidebar-primary: oklch(0.55 0.16 250); + --sidebar-primary-foreground: oklch(0.98 0.01 250); + --sidebar-accent: oklch(0.92 0.02 250); + --sidebar-accent-foreground: oklch(0.30 0.02 250); + --sidebar-border: oklch(0.88 0.015 240); + --sidebar-ring: oklch(0.55 0.16 250); } .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --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.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); + --background: oklch(0.17 0.02 250); + --foreground: oklch(0.94 0.01 240); + + --card: oklch(0.21 0.02 250); + --card-foreground: oklch(0.94 0.01 240); + + --popover: oklch(0.23 0.02 250); + --popover-foreground: oklch(0.94 0.01 240); + + /* Strong but not neon */ + --primary: oklch(0.65 0.17 250); + --primary-foreground: oklch(0.12 0.02 250); + + --secondary: oklch(0.27 0.02 250); + --secondary-foreground: oklch(0.94 0.01 240); + + --muted: oklch(0.25 0.02 250); + --muted-foreground: oklch(0.70 0.02 240); + + /* Accent for graph edges / highlights */ + --accent: oklch(0.60 0.18 280); + --accent-foreground: oklch(0.96 0.01 240); + + --destructive: oklch(0.68 0.20 25); + + --border: oklch(0.30 0.02 250); + --input: oklch(0.30 0.02 250); + --ring: oklch(0.65 0.17 250); + + /* Chart colors (balanced + readable on dark canvas) */ + --chart-1: oklch(0.65 0.17 250); + --chart-2: oklch(0.70 0.14 180); + --chart-3: oklch(0.72 0.18 300); + --chart-4: oklch(0.75 0.15 140); + --chart-5: oklch(0.72 0.20 40); + + --sidebar: oklch(0.19 0.02 250); + --sidebar-foreground: oklch(0.92 0.01 240); + --sidebar-primary: oklch(0.65 0.17 250); + --sidebar-primary-foreground: oklch(0.12 0.02 250); + --sidebar-accent: oklch(0.27 0.02 250); + --sidebar-accent-foreground: oklch(0.92 0.01 240); + --sidebar-border: oklch(0.30 0.02 250); + --sidebar-ring: oklch(0.65 0.17 250); } @layer base { diff --git a/src/app/workspace/page.tsx b/src/app/workspace/page.tsx index 2eb3af4..3407d29 100644 --- a/src/app/workspace/page.tsx +++ b/src/app/workspace/page.tsx @@ -6,14 +6,19 @@ import { useWorkspace } from "@/hooks/workspace"; import { ChevronRight } from "lucide-react"; import Cookies from "js-cookie"; import { useEffect, useState } from "react"; -import { EntityId } from "@/lib/types"; +import { Route } from "@/lib/types"; +import { Button } from "@/components/ui/button"; +import { + createDefaultWorkspace, + saveWorkspaceToLocalStorage, +} from "@/lib/workspace"; export default function Workspace() { const [currentWorkspace, setCurrentWorkspace] = useState(); const { workspace, loadWorkspace } = useWorkspace(); - const [route, setRoute] = useState(); + const [route, setRoute] = useState({}); useEffect(() => { setCurrentWorkspace(Cookies.get("workspace")); @@ -21,6 +26,8 @@ export default function Workspace() { useEffect(() => { loadWorkspace(currentWorkspace); + if (currentWorkspace) Cookies.set("workspace", currentWorkspace); + else Cookies.remove("workspace"); }, [currentWorkspace]); return workspace ? ( @@ -30,12 +37,23 @@ export default function Workspace() {
{workspace.name} - {workspace.entities[route || ""]?.name} + {workspace.entities[route.entity || ""]?.name}
- ) : null; + ) : ( +
{ + const w = createDefaultWorkspace(); + saveWorkspaceToLocalStorage(w); + setCurrentWorkspace(w.id); + }} + > + +
+ ); } diff --git a/src/components/sidebar/AppSidebar.tsx b/src/components/sidebar/AppSidebar.tsx index 3e31d16..645a1d7 100644 --- a/src/components/sidebar/AppSidebar.tsx +++ b/src/components/sidebar/AppSidebar.tsx @@ -16,7 +16,7 @@ import { DropdownMenuTrigger, } from "../ui/dropdown-menu"; import { ChevronDown } from "lucide-react"; -import { EntityId, SetState, Workspace } from "@/lib/types"; +import { EntityId, Route, SetState, Workspace } from "@/lib/types"; export default function AppSidebar({ children, @@ -25,7 +25,7 @@ export default function AppSidebar({ }: Readonly<{ children: React.ReactNode; workspace: Workspace; - setRoute: SetState; + setRoute: SetState; }>) { return ( diff --git a/src/components/sidebar/Entity.tsx b/src/components/sidebar/Entity.tsx index 7260165..6e0f8ea 100644 --- a/src/components/sidebar/Entity.tsx +++ b/src/components/sidebar/Entity.tsx @@ -9,7 +9,7 @@ import { } from "../ui/sidebar"; import { Collapsible, CollapsibleContent } from "../ui/collapsible"; import { ChevronDown } from "lucide-react"; -import { EntityId, SetState, Workspace } from "@/lib/types"; +import { EntityId, Route, SetState, Workspace } from "@/lib/types"; export type SidebarEntity = | { @@ -29,7 +29,7 @@ export default function EntitySwitch({ }: { entity: SidebarEntity; workspace: Workspace; - setRoute: SetState; + setRoute: SetState; }) { if (entity.kind === "group") { return ( @@ -65,7 +65,7 @@ export default function EntitySwitch({ { - setRoute(entity.id); + setRoute({ workspace: workspace.id, entity: entity.id }); }} > {workspace.entities[entity.id].name} diff --git a/src/lib/types.ts b/src/lib/types.ts index 0aa6331..70f2463 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -6,6 +6,11 @@ export type EntityId = string; export type TagId = string; export type TaskId = string; +export interface Route { + workspace?: string; + entity?: EntityId; +} + export interface Workspace { id: string; name: string;