---
description: Configure dark mode for your framework
argument-hint: "[framework]"
allowed-tools: Read, Write, Edit, Bash
---
Set up dark mode with theme switching for your specific framework.
## Instructions
Based on the framework detected or specified:
1. Install required dependencies
2. Set up theme provider
3. Configure CSS variables
4. Create theme toggle component
5. Set up persistence (cookies/localStorage)
## Framework Configurations
### Next.js (App Router)
```bash
npm install next-themes
```
Create `components/theme-provider.tsx`:
```tsx
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return {children}
}
```
Wrap in `app/layout.tsx`:
```tsx
{children}
```
### Vite
Create `components/theme-provider.tsx`:
```tsx
import { createContext, useContext, useEffect, useState } from "react"
type Theme = "dark" | "light" | "system"
const ThemeProviderContext = createContext<{
theme: Theme
setTheme: (theme: Theme) => void
}>({
theme: "system",
setTheme: () => null,
})
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState(
() => (localStorage.getItem("theme") as Theme) || "system"
)
useEffect(() => {
const root = window.document.documentElement
root.classList.remove("light", "dark")
if (theme === "system") {
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light"
root.classList.add(systemTheme)
return
}
root.classList.add(theme)
}, [theme])
const value = {
theme,
setTheme: (theme: Theme) => {
localStorage.setItem("theme", theme)
setTheme(theme)
},
}
return (
{children}
)
}
export const useTheme = () => {
const context = useContext(ThemeProviderContext)
if (context === undefined)
throw new Error("useTheme must be used within a ThemeProvider")
return context
}
```
### Remix
```bash
npm install remix-themes
```
In `app/root.tsx`:
```tsx
import { themeSessionResolver } from "remix-themes"
import {
PreventFlashOnWrongTheme,
ThemeProvider,
useTheme,
} from "remix-themes"
export async function loader({ request }: LoaderFunctionArgs) {
const { getTheme } = await themeSessionResolver(request)
return { theme: getTheme() }
}
export default function App() {
const data = useLoaderData()
const [theme] = useTheme()
return (
)
}
```
### Astro
In layout file:
```astro
```
## Theme Toggle Component
Create `components/theme-toggle.tsx`:
```tsx
import { Moon, Sun } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { useTheme } from "@/components/theme-provider" // or "next-themes"
export function ThemeToggle() {
const { setTheme } = useTheme()
return (
setTheme("light")}>
Light
setTheme("dark")}>
Dark
setTheme("system")}>
System
)
}
```
## CSS Configuration
Ensure `globals.css` has:
```css
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
/* ... other variables ... */
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... other variables ... */
}
}
```
## Example
If the user says: `/setup-dark-mode next`
1. Install next-themes
2. Create ThemeProvider component
3. Wrap app in ThemeProvider
4. Create ThemeToggle component
5. Add to navigation/header
6. Test theme switching