A Dropdown Menu to toggle between light and dark mode.
Create the component ~/components/mode-toggle.tsx
and paste the following code into it.
import { As } from "@kobalte/core"
import { Icons } from "~/components/icons"
import { Button } from "~/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from "~/components/ui/dropdown-menu"
export function ModeToggle() {
const setTheme = (theme: string) => {
localStorage.setItem("theme", theme)
const root = document.documentElement
if (theme === "light") {
root.classList.remove("dark")
} else {
root.classList.add("dark")
}
}
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<As component={Button} variant="ghost" size="sm" class="w-9 px-0">
<Icons.sun class="rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Icons.moon class="absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span class="sr-only">Toggle theme</span>
</As>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onSelect={() => setTheme("light")}>
<Icons.sun class="mr-2 h-4 w-4" />
<span>Light</span>
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => setTheme("dark")}>
<Icons.moon class="mr-2 h-4 w-4" />
<span>Dark</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}
You also need this little script somewhere in the <head />
to load the last selected mode on refresh.
const root = document.documentElement
const theme = localStorage.getItem("theme")
if (theme === "dark") {
root.classList.add("dark")
} else {
root.classList.remove("dark")
}