Jason Kneen commited on
Commit
9ca7165
·
1 Parent(s): e87a324

3 theme modes (light, sunset, dark)

Browse files
.gitignore CHANGED
@@ -38,4 +38,6 @@ yarn-error.log*
38
 
39
  # typescript
40
  *.tsbuildinfo
41
- next-env.d.ts
 
 
 
38
 
39
  # typescript
40
  *.tsbuildinfo
41
+ next-env.d.ts
42
+ .env
43
+ CLAUDE.md
app/globals.css CHANGED
@@ -3,6 +3,8 @@
3
  @plugin "tailwindcss-animate";
4
 
5
  @custom-variant dark (&:is(.dark *));
 
 
6
 
7
  :root {
8
  --background: oklch(0.99 0.01 56.32);
@@ -98,6 +100,100 @@
98
  --shadow-2xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.22);
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  @theme inline {
102
  --color-background: var(--background);
103
  --color-foreground: var(--foreground);
@@ -170,6 +266,7 @@
170
  /* Hide scrollbar for IE, Edge and Firefox */
171
  .no-scrollbar {
172
  -ms-overflow-style: none; /* IE and Edge */
173
- scrollbar-width: none; /* Firefox */
 
174
  }
175
  }
 
3
  @plugin "tailwindcss-animate";
4
 
5
  @custom-variant dark (&:is(.dark *));
6
+ @custom-variant sunset (&:is(.sunset *));
7
+ @custom-variant black (&:is(.black *));
8
 
9
  :root {
10
  --background: oklch(0.99 0.01 56.32);
 
100
  --shadow-2xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.22);
101
  }
102
 
103
+ .sunset {
104
+ --background: oklch(0.98 0.03 80.00);
105
+ --foreground: oklch(0.34 0.01 2.77);
106
+ --card: oklch(1.00 0 0);
107
+ --card-foreground: oklch(0.34 0.01 2.77);
108
+ --popover: oklch(1.00 0 0);
109
+ --popover-foreground: oklch(0.34 0.01 2.77);
110
+ --primary: oklch(0.65 0.26 34.00);
111
+ --primary-foreground: oklch(1.00 0 0);
112
+ --secondary: oklch(0.96 0.05 60.00);
113
+ --secondary-foreground: oklch(0.56 0.13 32.74);
114
+ --muted: oklch(0.97 0.02 39.40);
115
+ --muted-foreground: oklch(0.49 0.05 26.45);
116
+ --accent: oklch(0.83 0.22 50.00);
117
+ --accent-foreground: oklch(0.34 0.01 2.77);
118
+ --destructive: oklch(0.61 0.21 22.24);
119
+ --destructive-foreground: oklch(1.00 0 0);
120
+ --border: oklch(0.93 0.06 60.00);
121
+ --input: oklch(0.93 0.06 60.00);
122
+ --ring: oklch(0.65 0.26 34.00);
123
+ --chart-1: oklch(0.65 0.26 34.00);
124
+ --chart-2: oklch(0.83 0.22 50.00);
125
+ --chart-3: oklch(0.88 0.15 54.93);
126
+ --chart-4: oklch(0.82 0.20 40.89);
127
+ --chart-5: oklch(0.64 0.18 32.07);
128
+ --sidebar: oklch(0.97 0.04 70.00);
129
+ --sidebar-foreground: oklch(0.34 0.01 2.77);
130
+ --sidebar-primary: oklch(0.65 0.26 34.00);
131
+ --sidebar-primary-foreground: oklch(1.00 0 0);
132
+ --sidebar-accent: oklch(0.83 0.22 50.00);
133
+ --sidebar-accent-foreground: oklch(0.34 0.01 2.77);
134
+ --sidebar-border: oklch(0.93 0.06 60.00);
135
+ --sidebar-ring: oklch(0.65 0.26 34.00);
136
+ --font-sans: Montserrat, sans-serif;
137
+ --font-serif: Merriweather, serif;
138
+ --font-mono: Ubuntu Mono, monospace;
139
+ --radius: 0.625rem;
140
+ --shadow-2xs: 0px 6px 12px -3px hsl(0 0% 0% / 0.04);
141
+ --shadow-xs: 0px 6px 12px -3px hsl(0 0% 0% / 0.04);
142
+ --shadow-sm: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 1px 2px -4px hsl(0 0% 0% / 0.09);
143
+ --shadow: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 1px 2px -4px hsl(0 0% 0% / 0.09);
144
+ --shadow-md: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 2px 4px -4px hsl(0 0% 0% / 0.09);
145
+ --shadow-lg: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 4px 6px -4px hsl(0 0% 0% / 0.09);
146
+ --shadow-xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 8px 10px -4px hsl(0 0% 0% / 0.09);
147
+ --shadow-2xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.22);
148
+ }
149
+
150
+ .black {
151
+ --background: oklch(0.15 0.01 350.00);
152
+ --foreground: oklch(0.95 0.01 60.00);
153
+ --card: oklch(0.20 0.01 340.00);
154
+ --card-foreground: oklch(0.95 0.01 60.00);
155
+ --popover: oklch(0.20 0.01 340.00);
156
+ --popover-foreground: oklch(0.95 0.01 60.00);
157
+ --primary: oklch(0.45 0.10 35.00);
158
+ --primary-foreground: oklch(1.00 0 0);
159
+ --secondary: oklch(0.25 0.01 340.00);
160
+ --secondary-foreground: oklch(0.95 0.01 60.00);
161
+ --muted: oklch(0.22 0.01 340.00);
162
+ --muted-foreground: oklch(0.86 0.01 60.00);
163
+ --accent: oklch(0.70 0.09 58.00);
164
+ --accent-foreground: oklch(0.15 0.01 350.00);
165
+ --destructive: oklch(0.45 0.16 20.00);
166
+ --destructive-foreground: oklch(1.00 0 0);
167
+ --border: oklch(0.25 0.01 340.00);
168
+ --input: oklch(0.25 0.01 340.00);
169
+ --ring: oklch(0.45 0.10 35.00);
170
+ --chart-1: oklch(0.45 0.10 35.00);
171
+ --chart-2: oklch(0.70 0.09 58.00);
172
+ --chart-3: oklch(0.80 0.06 54.00);
173
+ --chart-4: oklch(0.75 0.08 40.00);
174
+ --chart-5: oklch(0.55 0.10 32.00);
175
+ --sidebar: oklch(0.15 0.01 350.00);
176
+ --sidebar-foreground: oklch(0.95 0.01 60.00);
177
+ --sidebar-primary: oklch(0.40 0.06 34.00);
178
+ --sidebar-primary-foreground: oklch(1.00 0 0);
179
+ --sidebar-accent: oklch(0.60 0.07 56.00);
180
+ --sidebar-accent-foreground: oklch(0.15 0.01 350.00);
181
+ --sidebar-border: oklch(0.25 0.01 340.00);
182
+ --sidebar-ring: oklch(0.45 0.10 35.00);
183
+ --font-sans: Montserrat, sans-serif;
184
+ --font-serif: Merriweather, serif;
185
+ --font-mono: Ubuntu Mono, monospace;
186
+ --radius: 0.625rem;
187
+ --shadow-2xs: 0px 6px 12px -3px hsl(0 0% 0% / 0.04);
188
+ --shadow-xs: 0px 6px 12px -3px hsl(0 0% 0% / 0.04);
189
+ --shadow-sm: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 1px 2px -4px hsl(0 0% 0% / 0.09);
190
+ --shadow: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 1px 2px -4px hsl(0 0% 0% / 0.09);
191
+ --shadow-md: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 2px 4px -4px hsl(0 0% 0% / 0.09);
192
+ --shadow-lg: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 4px 6px -4px hsl(0 0% 0% / 0.09);
193
+ --shadow-xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.09), 0px 8px 10px -4px hsl(0 0% 0% / 0.09);
194
+ --shadow-2xl: 0px 6px 12px -3px hsl(0 0% 0% / 0.22);
195
+ }
196
+
197
  @theme inline {
198
  --color-background: var(--background);
199
  --color-foreground: var(--foreground);
 
266
  /* Hide scrollbar for IE, Edge and Firefox */
267
  .no-scrollbar {
268
  -ms-overflow-style: none; /* IE and Edge */
269
+ /* Use Firefox-specific scrollbar hiding when supported */
270
+ scrollbar-width: none;
271
  }
272
  }
app/providers.tsx CHANGED
@@ -30,8 +30,9 @@ export function Providers({ children }: { children: ReactNode }) {
30
  <ThemeProvider
31
  attribute="class"
32
  defaultTheme="system"
33
- enableSystem
34
  disableTransitionOnChange
 
35
  >
36
  <MCPProvider>
37
  <SidebarProvider defaultOpen={sidebarOpen} open={sidebarOpen} onOpenChange={setSidebarOpen}>
 
30
  <ThemeProvider
31
  attribute="class"
32
  defaultTheme="system"
33
+ enableSystem={true}
34
  disableTransitionOnChange
35
+ themes={["light", "dark", "sunset", "black"]}
36
  >
37
  <MCPProvider>
38
  <SidebarProvider defaultOpen={sidebarOpen} open={sidebarOpen} onOpenChange={setSidebarOpen}>
components/theme-toggle.tsx CHANGED
@@ -1,24 +1,44 @@
1
  "use client"
2
 
3
  import * as React from "react"
4
- import { Moon, Sun } from "lucide-react"
5
  import { useTheme } from "next-themes"
6
  import { Button } from "./ui/button"
 
 
7
 
8
  export function ThemeToggle({ className, ...props }: React.ComponentProps<typeof Button>) {
9
  const { theme, setTheme } = useTheme()
10
 
11
  return (
12
- <Button
13
- variant="ghost"
14
- size="icon"
15
- onClick={() => setTheme(theme === "light" ? "dark" : "light")}
16
- className={`rounded-md h-8 w-8 ${className}`}
17
- {...props}
18
- >
19
- <Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0 hover:text-sidebar-accent" />
20
- <Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100 hover:text-sidebar-accent" />
21
- <span className="sr-only">Toggle theme</span>
22
- </Button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  )
24
- }
 
1
  "use client"
2
 
3
  import * as React from "react"
4
+ import { CircleDashed, Flame, Sun } from "lucide-react"
5
  import { useTheme } from "next-themes"
6
  import { Button } from "./ui/button"
7
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./ui/dropdown-menu"
8
+ import { cn } from "@/lib/utils"
9
 
10
  export function ThemeToggle({ className, ...props }: React.ComponentProps<typeof Button>) {
11
  const { theme, setTheme } = useTheme()
12
 
13
  return (
14
+ <DropdownMenu>
15
+ <DropdownMenuTrigger asChild={true}>
16
+ <Button
17
+ variant="ghost"
18
+ size="icon"
19
+ className={cn(`rounded-md h-8 w-8`, className)}
20
+ {...props}
21
+ >
22
+ <Flame className="h-4 w-4 rotate-0 scale-100 transition-all light:scale-0 light:-rotate-90 black:scale-0 black:-rotate-90 hover:text-sidebar-accent" />
23
+ <Sun className="absolute h-4 w-4 rotate-90 scale-0 transition-all light:rotate-0 light:scale-100 black:scale-0 black:rotate-0 hover:text-sidebar-accent" />
24
+ <CircleDashed className="absolute h-4 w-4 rotate-90 scale-0 transition-all black:rotate-0 black:scale-100 light:scale-0 light:rotate-0 hover:text-sidebar-accent" />
25
+ <span className="sr-only">Toggle theme</span>
26
+ </Button>
27
+ </DropdownMenuTrigger>
28
+ <DropdownMenuContent align="end">
29
+ <DropdownMenuItem onSelect={() => setTheme("dark")}>
30
+ <Flame className="mr-2 h-4 w-4" />
31
+ <span>Sunset</span>
32
+ </DropdownMenuItem>
33
+ <DropdownMenuItem onSelect={() => setTheme("light")}>
34
+ <Sun className="mr-2 h-4 w-4" />
35
+ <span>Light</span>
36
+ </DropdownMenuItem>
37
+ <DropdownMenuItem onSelect={() => setTheme("black")}>
38
+ <CircleDashed className="mr-2 h-4 w-4" />
39
+ <span>Dark</span>
40
+ </DropdownMenuItem>
41
+ </DropdownMenuContent>
42
+ </DropdownMenu>
43
  )
44
+ }
lib/context/mcp-context.tsx CHANGED
@@ -42,7 +42,8 @@ interface MCPContextType {
42
 
43
  const MCPContext = createContext<MCPContextType | undefined>(undefined);
44
 
45
- export function MCPProvider({ children }: { children: React.ReactNode }) {
 
46
  const [mcpServers, setMcpServers] = useLocalStorage<MCPServer[]>(
47
  STORAGE_KEYS.MCP_SERVERS,
48
  []
 
42
 
43
  const MCPContext = createContext<MCPContextType | undefined>(undefined);
44
 
45
+ export function MCPProvider(props: { children: React.ReactNode }) {
46
+ const { children } = props;
47
  const [mcpServers, setMcpServers] = useLocalStorage<MCPServer[]>(
48
  STORAGE_KEYS.MCP_SERVERS,
49
  []
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json CHANGED
@@ -53,6 +53,7 @@
53
  "next": "^15.3.1",
54
  "next-auth": "^4.24.11",
55
  "next-themes": "^0.4.6",
 
56
  "pg": "^8.14.1",
57
  "react": "^19.1.0",
58
  "react-dom": "^19.1.0",
 
53
  "next": "^15.3.1",
54
  "next-auth": "^4.24.11",
55
  "next-themes": "^0.4.6",
56
+ "or": "^0.2.0",
57
  "pg": "^8.14.1",
58
  "react": "^19.1.0",
59
  "react-dom": "^19.1.0",