Skip to content

Commit 3f3844d

Browse files
committed
feat: add 'Claude' theme — true black, blue accent, premium squircle aesthetic
New theme inspired by Claude Desktop, Linear, and Beam: - True black canvas (#000000) - Blue primary accent (#3b82f6) - Heavy border-radius (12-24px squircle) - Subtle borders (5-8% white opacity) - Premium soft shadows - Refined syntax highlighting - Dark + light variants - Set as default theme
1 parent bfe5e17 commit 3f3844d

2 files changed

Lines changed: 278 additions & 3 deletions

File tree

app/globals.css

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,218 @@
337337
--radius-lg: 16px;
338338
}
339339

340+
/* ══════════════════════════════════════════════════════════════════
341+
Theme: Claude — Premium ultra-modern aesthetic
342+
══════════════════════════════════════════════════════════════════ */
343+
344+
/* ── Claude Dark ──────────────────────────────────────────────── */
345+
.dark[data-theme='claude'] {
346+
/* True black canvas with deep purple undertones */
347+
--bg: #000000;
348+
--bg-elevated: #0a0a0a;
349+
--bg-subtle: #111111;
350+
--bg-secondary: #080808;
351+
--bg-tertiary: #141414;
352+
--sidebar-bg: #000000;
353+
--foreground: #f0f0f0;
354+
--subtle: #555;
355+
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
356+
--font-mono: 'JetBrains Mono', 'SF Mono', monospace;
357+
358+
/* Blue primary accent (instead of red) */
359+
--brand: #3b82f6;
360+
--brand-hover: #2563eb;
361+
--brand-muted: rgba(59, 130, 246, 0.10);
362+
--brand-deep: #1d4ed8;
363+
--brand-chat: #3b82f6;
364+
--brand-contrast: #ffffff;
365+
--brand-glow: rgba(59, 130, 246, 0.12);
366+
--brand-glow-subtle: rgba(59, 130, 246, 0.04);
367+
368+
/* Status colors */
369+
--success: #22c55e;
370+
--warning: #eab308;
371+
--error: #ef4444;
372+
--info: #3b82f6;
373+
374+
/* Text hierarchy */
375+
--text-primary: #f0f0f0;
376+
--text-secondary: #888;
377+
--text-tertiary: #555;
378+
--text-disabled: #444;
379+
380+
/* Syntax tokens (refined for true black) */
381+
--syntax-comment: #555555;
382+
--syntax-keyword: #a78bfa;
383+
--syntax-string: #6ee7b7;
384+
--syntax-string-escape: #34d399;
385+
--syntax-number: #fbbf24;
386+
--syntax-regexp: #f87171;
387+
--syntax-type: #67e8f9;
388+
--syntax-function: #93c5fd;
389+
--syntax-variable: #e2e8f0;
390+
--syntax-variable-predefined: #fca5a5;
391+
--syntax-constant: #fbbf24;
392+
--syntax-tag: #f87171;
393+
--syntax-attribute-name: #a78bfa;
394+
--syntax-attribute-value: #6ee7b7;
395+
--syntax-delimiter: #666666;
396+
--syntax-operator: #888888;
397+
398+
/* Subtle borders (barely visible) */
399+
--border: rgba(255, 255, 255, 0.06);
400+
--border-hover: rgba(255, 255, 255, 0.10);
401+
--border-focus: #3b82f6;
402+
403+
/* Glass (less blur, more subtle) */
404+
--glass-bg: rgba(0, 0, 0, 0.95);
405+
--glass-bg-hover: rgba(10, 10, 10, 0.95);
406+
--glass-bg-elevated: rgba(14, 14, 14, 0.95);
407+
--glass-border: rgba(255, 255, 255, 0.06);
408+
--glass-border-hover: rgba(255, 255, 255, 0.10);
409+
--glass-shadow: rgba(0, 0, 0, 0.8);
410+
411+
/* Larger radius (squircle feel) */
412+
--radius-sm: 12px;
413+
--radius-md: 16px;
414+
--radius-lg: 24px;
415+
416+
/* Premium shadows (soft, large radius, low opacity) */
417+
--shadow-2xs: 0 1px 2px rgba(0, 0, 0, 0.3);
418+
--shadow-xs: 0 2px 4px rgba(0, 0, 0, 0.3);
419+
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.4);
420+
--shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
421+
--shadow-md: 0 6px 24px rgba(0, 0, 0, 0.5);
422+
--shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.6);
423+
--shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.7);
424+
--shadow-2xl: 0 32px 80px rgba(0, 0, 0, 0.8), 0 0 40px rgba(59, 130, 246, 0.06);
425+
426+
/* VSCode-like tokens */
427+
--kn-claw: var(--brand);
428+
--vscode-text: var(--text-primary);
429+
--vscode-subtle: var(--text-tertiary);
430+
--vscode-muted: var(--text-secondary);
431+
432+
/* Overlays and misc */
433+
--overlay: rgba(0, 0, 0, 0.6);
434+
--logo-filter: none;
435+
436+
/* Scrollbar */
437+
--scrollbar-thumb: rgba(255, 255, 255, 0.08);
438+
--scrollbar-thumb-hover: rgba(255, 255, 255, 0.15);
439+
440+
/* Header */
441+
--header-glass-bg: rgba(0, 0, 0, 0.95);
442+
443+
/* Shimmer effects */
444+
--shimmer-from: var(--bg-elevated);
445+
--shimmer-via: var(--bg-subtle);
446+
}
447+
448+
/* ── Claude Light ─────────────────────────────────────────────── */
449+
[data-theme='claude']:not(.dark) {
450+
/* Clean, bright light variant */
451+
--bg: #ffffff;
452+
--bg-elevated: #fafafa;
453+
--bg-subtle: #f5f5f5;
454+
--bg-secondary: #f8f8f8;
455+
--bg-tertiary: #f0f0f0;
456+
--sidebar-bg: #ffffff;
457+
--foreground: #0a0a0a;
458+
--subtle: #a3a3a3;
459+
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
460+
--font-mono: 'JetBrains Mono', 'SF Mono', monospace;
461+
462+
/* Blue primary accent */
463+
--brand: #3b82f6;
464+
--brand-hover: #2563eb;
465+
--brand-muted: rgba(59, 130, 246, 0.08);
466+
--brand-deep: #1d4ed8;
467+
--brand-chat: #eff6ff;
468+
--brand-contrast: #ffffff;
469+
--brand-glow: rgba(59, 130, 246, 0.10);
470+
--brand-glow-subtle: rgba(59, 130, 246, 0.03);
471+
472+
/* Status colors */
473+
--success: #16a34a;
474+
--warning: #ca8a04;
475+
--error: #dc2626;
476+
--info: #2563eb;
477+
478+
/* Text hierarchy */
479+
--text-primary: #0a0a0a;
480+
--text-secondary: #525252;
481+
--text-tertiary: #a3a3a3;
482+
--text-disabled: #d4d4d4;
483+
484+
/* Syntax tokens */
485+
--syntax-comment: #a3a3a3;
486+
--syntax-keyword: #7c3aed;
487+
--syntax-string: #16a34a;
488+
--syntax-string-escape: #15803d;
489+
--syntax-number: #b45309;
490+
--syntax-regexp: #dc2626;
491+
--syntax-type: #0891b2;
492+
--syntax-function: #2563eb;
493+
--syntax-variable: #0a0a0a;
494+
--syntax-variable-predefined: #dc2626;
495+
--syntax-constant: #b45309;
496+
--syntax-tag: #dc2626;
497+
--syntax-attribute-name: #7c3aed;
498+
--syntax-attribute-value: #16a34a;
499+
--syntax-delimiter: #525252;
500+
--syntax-operator: #525252;
501+
502+
/* Borders */
503+
--border: rgba(0, 0, 0, 0.08);
504+
--border-hover: rgba(0, 0, 0, 0.12);
505+
--border-focus: #3b82f6;
506+
507+
/* Glass */
508+
--glass-bg: rgba(255, 255, 255, 0.95);
509+
--glass-bg-hover: rgba(250, 250, 250, 0.95);
510+
--glass-bg-elevated: rgba(245, 245, 245, 0.95);
511+
--glass-border: rgba(0, 0, 0, 0.06);
512+
--glass-border-hover: rgba(0, 0, 0, 0.10);
513+
--glass-shadow: rgba(0, 0, 0, 0.05);
514+
515+
/* Radius */
516+
--radius-sm: 12px;
517+
--radius-md: 16px;
518+
--radius-lg: 24px;
519+
520+
/* Shadows */
521+
--shadow-2xs: 0 1px 2px rgba(0, 0, 0, 0.03);
522+
--shadow-xs: 0 2px 4px rgba(0, 0, 0, 0.04);
523+
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
524+
--shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
525+
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08);
526+
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.10);
527+
--shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.08), 0 0 20px rgba(59, 130, 246, 0.04);
528+
--shadow-2xl: 0 24px 60px rgba(0, 0, 0, 0.10), 0 0 40px rgba(59, 130, 246, 0.05);
529+
530+
/* VSCode-like tokens */
531+
--kn-claw: var(--brand);
532+
--vscode-text: var(--text-primary);
533+
--vscode-subtle: var(--text-tertiary);
534+
--vscode-muted: var(--text-secondary);
535+
536+
/* Overlays and misc */
537+
--overlay: rgba(0, 0, 0, 0.35);
538+
--logo-filter: none;
539+
540+
/* Scrollbar */
541+
--scrollbar-thumb: rgba(0, 0, 0, 0.12);
542+
--scrollbar-thumb-hover: rgba(0, 0, 0, 0.20);
543+
544+
/* Header */
545+
--header-glass-bg: rgba(255, 255, 255, 0.95);
546+
547+
/* Shimmer effects */
548+
--shimmer-from: #f5f5f5;
549+
--shimmer-via: #ffffff;
550+
}
551+
340552
/* ══════════════════════════════════════════════════════════════════
341553
Theme: Bone — Pure black & white, stark monochrome
342554
══════════════════════════════════════════════════════════════════ */
@@ -1011,6 +1223,68 @@
10111223
--color-ai-hover-bg: rgba(0, 0, 0, 0.04);
10121224
}
10131225

1226+
/* Dark semantic colors (Claude — blue accent) */
1227+
.dark[data-theme='claude'] {
1228+
--color-additions: #3fb950;
1229+
--color-deletions: #f85149;
1230+
--on-additions: #ffffff;
1231+
--on-deletions: #ffffff;
1232+
--color-stage-review: #60a5fa;
1233+
--color-stage-review-bg: rgba(96, 165, 250, 0.1);
1234+
--color-stage-review-border: rgba(96, 165, 250, 0.3);
1235+
--color-stage-prepare: #fbbf24;
1236+
--color-stage-prepare-bg: rgba(251, 191, 36, 0.1);
1237+
--color-stage-prepare-border: rgba(251, 191, 36, 0.3);
1238+
--color-stage-merge: #34d399;
1239+
--color-stage-merge-bg: rgba(52, 211, 153, 0.1);
1240+
--color-stage-merge-border: rgba(52, 211, 153, 0.3);
1241+
--color-prereq-met: #34d399;
1242+
--color-prereq-unmet: #fbbf24;
1243+
--color-conflict: #f87171;
1244+
--color-stale: #fbbf24;
1245+
--color-merged: #3b82f6;
1246+
--color-merged-muted: rgba(59, 130, 246, 0.12);
1247+
--color-merged-border: rgba(59, 130, 246, 0.3);
1248+
--color-closed: #f87171;
1249+
--color-action-default: var(--text-secondary);
1250+
--color-ai: #93c5fd;
1251+
--color-ai-muted: rgba(147, 197, 253, 0.12);
1252+
--color-ai-border: rgba(147, 197, 253, 0.3);
1253+
--color-ai-hover: #bfdbfe;
1254+
--color-ai-hover-bg: rgba(147, 197, 253, 0.1);
1255+
}
1256+
1257+
/* Light semantic colors (Claude — blue accent) */
1258+
[data-theme='claude']:not(.dark) {
1259+
--color-additions: #16a34a;
1260+
--color-deletions: #dc2626;
1261+
--on-additions: #ffffff;
1262+
--on-deletions: #ffffff;
1263+
--color-stage-review: #2563eb;
1264+
--color-stage-review-bg: rgba(37, 99, 235, 0.08);
1265+
--color-stage-review-border: rgba(37, 99, 235, 0.25);
1266+
--color-stage-prepare: #b45309;
1267+
--color-stage-prepare-bg: rgba(180, 83, 9, 0.08);
1268+
--color-stage-prepare-border: rgba(180, 83, 9, 0.25);
1269+
--color-stage-merge: #16a34a;
1270+
--color-stage-merge-bg: rgba(22, 163, 74, 0.08);
1271+
--color-stage-merge-border: rgba(22, 163, 74, 0.25);
1272+
--color-prereq-met: #16a34a;
1273+
--color-prereq-unmet: #b45309;
1274+
--color-conflict: #dc2626;
1275+
--color-stale: #b45309;
1276+
--color-merged: #3b82f6;
1277+
--color-merged-muted: rgba(59, 130, 246, 0.08);
1278+
--color-merged-border: rgba(59, 130, 246, 0.25);
1279+
--color-closed: #dc2626;
1280+
--color-action-default: var(--text-secondary);
1281+
--color-ai: #2563eb;
1282+
--color-ai-muted: rgba(37, 99, 235, 0.08);
1283+
--color-ai-border: rgba(37, 99, 235, 0.25);
1284+
--color-ai-hover: #1d4ed8;
1285+
--color-ai-hover-bg: rgba(37, 99, 235, 0.08);
1286+
}
1287+
10141288
/* Light-mode .prose-chat overrides no longer needed — base rules use theme vars */
10151289

10161290
/* ──────────────────────────────────────────────────────────────────

context/theme-context.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
export type ThemeMode = 'light' | 'dark' | 'system'
1414
export type ResolvedMode = 'light' | 'dark'
15-
export type ThemeId = 'obsidian' | 'neon' | 'catppuccin-mocha' | 'bone' | 'supreme' | string
15+
export type ThemeId = 'obsidian' | 'neon' | 'catppuccin-mocha' | 'bone' | 'supreme' | 'claude' | string
1616

1717
export interface ThemePreset {
1818
id: ThemeId
@@ -22,6 +22,7 @@ export interface ThemePreset {
2222
}
2323

2424
export const THEME_PRESETS: ThemePreset[] = [
25+
{ id: 'claude', label: 'Claude', color: '#3b82f6', group: 'core' },
2526
{ id: 'supreme', label: 'Supreme', color: '#d2a34f', group: 'core' },
2627
{ id: 'codex', label: 'Codex', color: '#1f1f1f', group: 'core' },
2728
{ id: 'obsidian', label: 'Obsidian', color: '#ca3a29', group: 'core' },
@@ -98,7 +99,7 @@ function applyToDOM(themeId: string, resolved: ResolvedMode) {
9899
}
99100

100101
export function ThemeProvider({ children }: { children: ReactNode }) {
101-
const [themeId, setThemeIdState] = useState<ThemeId>('supreme')
102+
const [themeId, setThemeIdState] = useState<ThemeId>('claude')
102103
const [mode, setModeState] = useState<ThemeMode>('dark')
103104
const [resolvedMode, setResolvedMode] = useState<ResolvedMode>('dark')
104105
const [bgTint, setBgTintState] = useState(6)
@@ -112,7 +113,7 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
112113
try {
113114
const savedTheme = localStorage.getItem(STORAGE_THEME)
114115
const savedMode = localStorage.getItem(STORAGE_MODE) as ThemeMode | null
115-
const tid = savedTheme || 'supreme'
116+
const tid = savedTheme || 'claude'
116117
const md = savedMode || 'dark'
117118
const rm = resolveMode(md)
118119
const savedTint = localStorage.getItem(STORAGE_BG_TINT)

0 commit comments

Comments
 (0)