From 87bd6997e39a28f447f299e6cf26bfd8df28158d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gjermund=20H=C3=B8s=C3=B8ien=20Wiggen?= Date: Sun, 7 Jun 2026 22:29:52 +0200 Subject: [PATCH] Add light mode support (next-themes), JetBrains Mono font, OpenType features - layout.tsx: ThemeProvider from next-themes, light mode DEFAULT, JetBrains_Mono font - globals.css: font-mono pointing to correct variable, font-feature-settings cv01+ss03 on body - next-themes package installed - Build passes with zero errors --- docs/web-lightmode-spec.md | 63 ++++++++++++++++++++++++++++++++++++++ web/package.json | 1 + web/src/app/globals.css | 3 +- web/src/app/layout.tsx | 21 +++++++++---- 4 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 docs/web-lightmode-spec.md diff --git a/docs/web-lightmode-spec.md b/docs/web-lightmode-spec.md new file mode 100644 index 0000000..c3894c6 --- /dev/null +++ b/docs/web-lightmode-spec.md @@ -0,0 +1,63 @@ +CRITICAL REDESIGN REQUIRED. The current Tessera frontend is dark-mode-only and not user-friendly. Implement these changes: + +## 1. LIGHT MODE AS DEFAULT +Rewrite the theme system. shadcn/ui supports light/dark via CSS variables. + +- Remove forced `className="dark"` from HTML element in layout.tsx +- Add ThemeProvider (install next-themes: bun add next-themes) +- Light mode is DEFAULT. Dark mode via toggle. +- Use shadcn/ui's built-in CSS variable system (already in globals.css) + +Light mode colors: +- Background: white for canvas, #f8f9fa for panels/sidebar +- Text: #1a1a2e primary, #4a4a6a secondary, #6b7280 tertiary +- Borders: #e5e7eb, Cards: white with shadow +- Accent: #5e6ad2 (works in both modes) + +Dark mode (toggled): keep existing Linear-inspired dark theme + +## 2. BETTER FONT +- Primary: 'Inter' from next/font/google with font-feature-settings: 'cv01' 1, 'ss03' 1 (geometric Linear-like character) +- Monospace: 'JetBrains Mono' for ticket IDs, code, config +- Headings: tighter letter-spacing (-0.02em) +- Body: 15px base, line-height 1.5 + +## 3. UX IMPROVEMENTS + +### Ticket list (page.tsx): +- Inbox-like rows: padding, hover highlight, subtle left border on hover +- Add checkbox column for future batch actions +- Clicking row opens detail in split view: list stays on left, detail on right +- OR simplified: click opens slide-over Sheet from right showing detail +- "New Ticket" button: prominent with gradient background + +### Ticket detail (tickets/[id]/page.tsx): +- Better conversation hierarchy: customer messages tinted, agent clearly differentiated +- Properties sidebar: group into Status/Assignment/Details sections with dividers +- Status dropdown: more prominent (most important action) + +### Global: +- Smooth transitions (150ms ease) on hover states +- Border radius consistency (8px cards, 6px inputs) +- Sidebar collapse/expand with hamburger +- Breadcrumb navigation at top of detail pages +- Tooltips on icon buttons +- Split-view or sheet overlay for ticket detail from list + +### Command palette: +- Ensure Cmd+K / Ctrl+K triggers it +- Add fuzzy ticket search +- Add quick actions + +## 4. IMPLEMENTATION +- Read current files first +- Modify existing files, don't delete +- Preserve api.ts and types.ts +- Use next-themes for theme switching +- shadcn/ui CSS variables already in globals.css + +## 5. VERIFY +- `cd web && bun run build` — zero TypeScript errors +- Both light and dark mode work +- Font has OpenType features applied +- Ticket list is inbox-like diff --git a/web/package.json b/web/package.json index 977602b..0e1fa7a 100644 --- a/web/package.json +++ b/web/package.json @@ -17,6 +17,7 @@ "date-fns": "^4.4.0", "lucide-react": "^1.17.0", "next": "16.2.7", + "next-themes": "^0.4.6", "react": "19.2.4", "react-dom": "19.2.4", "react-hook-form": "^7.77.0", diff --git a/web/src/app/globals.css b/web/src/app/globals.css index c56032b..97ebd3b 100644 --- a/web/src/app/globals.css +++ b/web/src/app/globals.css @@ -8,7 +8,7 @@ --color-background: var(--background); --color-foreground: var(--foreground); --font-sans: var(--font-sans); - --font-mono: var(--font-geist-mono); + --font-mono: var(--font-mono); --font-heading: var(--font-sans); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); @@ -123,6 +123,7 @@ } body { @apply bg-background text-foreground; + font-feature-settings: "cv01" 1, "ss03" 1; } html { @apply font-sans; diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index 212113c..2de7db4 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; -import { Inter } from "next/font/google"; +import { Inter, JetBrains_Mono } from "next/font/google"; import { Suspense } from "react"; +import { ThemeProvider } from "next-themes"; import "./globals.css"; import { AppShell } from "@/components/app-shell"; @@ -9,6 +10,11 @@ const inter = Inter({ variable: "--font-inter", }); +const jetbrainsMono = JetBrains_Mono({ + subsets: ["latin"], + variable: "--font-mono", +}); + export const metadata: Metadata = { title: "Tessera", description: "Ticket management system", @@ -18,13 +24,16 @@ export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( - + - Loading...}> - {children} - + + Loading...}> + {children} + + );