System preference and a manual theme toggle
A system-preference theme respects the user's operating-system setting. A manual toggle lets the user override that preference. For a manual theme, your app typically stores a theme choice, updates the selector or class that activates dark mode, and prevents a flash of the wrong theme during initial rendering.
In server-rendered frameworks, theme initialization can cause hydration differences if the server and client render different markup. Use a framework-appropriate theme strategy and test the first paint, refresh, and navigation. Never assume a CSS variant alone creates a functioning toggle.
Tailwind styles the theme states. Your app still needs to decide where the theme value lives, how it persists, and how the active dark selector is applied.
function ThemeToggle({ theme, setTheme }) {
const isDark = theme === "dark";
return (
<button
type="button"
aria-pressed={isDark}
onClick={() => setTheme(isDark ? "light" : "dark")}
className="rounded-lg border px-3 py-2 text-sm font-medium focus-visible:outline-2 focus-visible:outline-offset-2"
>
Switch to {isDark ? "light" : "dark"} mode
</button>
);
}theme, and that the application's dark selector is wired to that state. aria-pressed communicates the toggle state. The code alone does not add or remove a class on the document.