dark-light-modes
Dark/Light Modes
Agent Workflow (MANDATORY)
Before implementation, use TeamCreate to spawn 3 agents:
- fuse-ai-pilot:explore-codebase - Check existing theme setup
- fuse-ai-pilot:research-expert - next-themes or theme provider docs
After: Run fuse-ai-pilot:sniper for validation.
Overview
| Feature | Description |
|---|---|
| CSS Variables | Token-based theming |
| System Detection | prefers-color-scheme |
| Manual Toggle | User preference |
| No FOUC | Prevent flash |
Quick Reference
CSS Variables
:root {
--background: oklch(100% 0 0);
--foreground: oklch(10% 0 0);
--glass-bg: rgba(255, 255, 255, 0.8);
}
.dark {
--background: oklch(10% 0.01 260);
--foreground: oklch(98% 0 0);
--glass-bg: rgba(0, 0, 0, 0.4);
}
System Preference
@media (prefers-color-scheme: dark) {
:root:not(.light) {
--background: oklch(10% 0.01 260);
}
}
Next.js with next-themes
// app/providers.tsx
"use client";
import { ThemeProvider } from "next-themes";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
);
}
Theme Toggle
"use client";
import { Moon, Sun, Monitor } from "lucide-react";
import { useTheme } from "next-themes";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<div className="flex gap-1 p-1 bg-muted rounded-lg">
<button onClick={() => setTheme("light")}>
<Sun className="h-4 w-4" />
</button>
<button onClick={() => setTheme("dark")}>
<Moon className="h-4 w-4" />
</button>
<button onClick={() => setTheme("system")}>
<Monitor className="h-4 w-4" />
</button>
</div>
);
}
Prevent FOUC
<html suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{
__html: `
(function() {
const theme = localStorage.getItem('theme') || 'system';
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (theme === 'dark' || (theme === 'system' && systemDark)) {
document.documentElement.classList.add('dark');
}
})();
`,
}} />
</head>
Validation Checklist
[ ] CSS variables for both modes
[ ] prefers-color-scheme respected
[ ] Manual toggle available
[ ] No FOUC (flash of unstyled content)
[ ] Glass variants for both modes
[ ] Stored preference in localStorage
Best Practices
DO
- Use CSS variables for theming
- Support system preference
- Provide manual toggle
- Prevent FOUC with script
DON'T
- Hard-code dark: classes everywhere
- Ignore system preference
- Forget localStorage
- Allow flash on load
More from fusengine/agents
laravel-architecture
Design Laravel app architecture with services, repositories, actions, and clean code patterns. Use when structuring projects, creating services, implementing DI, or organizing code layers.
97laravel-blade
Create Blade templates with components, slots, layouts, and directives. Use when building views, reusable components, or templating.
88laravel-livewire
Livewire 3 reactive components - wire:model, actions, events, Volt, Folio. Use when building reactive UI without JavaScript.
85nextjs-i18n
Next.js 16 internationalization with next-intl or DIY. Use when implementing i18n, translations, localization, multilingual, language switch, locale routing, or formatters.
59solid-php
SOLID principles for Laravel 12 and PHP 8.5. Files < 100 lines, interfaces separated, PHPDoc mandatory. Auto-detects Laravel and FuseCore architecture.
51laravel-testing
Write tests with Pest 3/PHPUnit, feature tests, unit tests, mocking, fakes, and factories. Use when testing controllers, services, models, or implementing TDD.
50