Light and Dark Mode
Add this line to your global CSS file (e.g. globals.css) — it's a one-time setup step, not part of the component below.
@custom-variant dark (&:where(.dark, .dark *));components/ThemeToggle.js
'use client' import { useEffect, useState } from 'react' import Image from 'next/image' export default function ThemeToggle() { const [theme, setTheme] = useState('light') useEffect(() => { const saved = localStorage.getItem('theme') if (saved) { setTheme(saved) document.documentElement.classList.toggle('dark', saved === 'dark') } else { const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches const initial = systemDark ? 'dark' : 'light' setTheme(initial) document.documentElement.classList.toggle('dark', systemDark) } }, []) const toggleTheme = () => { const newTheme = theme === 'dark' ? 'light' : 'dark' setTheme(newTheme) localStorage.setItem('theme', newTheme) document.documentElement.classList.toggle('dark', newTheme === 'dark') } return ( <div onClick={toggleTheme} className="relative w-16 h-8 flex items-center bg-[#ffffff] dark:bg-[#2a2a2a] border-2 border-[#e8e8e8] dark:border-[#4c4c4c] rounded-full cursor-pointer transition-colors duration-300"> <div className={'absolute left-1 transition-transform duration-300 ease-in-out ' + (theme === 'dark' ? 'translate-x-6' : '')}> <div className="w-8 h-6 flex items-center justify-center rounded-full"> {theme === 'light' ? ( <Image src="/icons/sun.svg" alt="Sun" width={20} height={20} /> ) : ( <Image src="/icons/moon.svg" alt="Moon" width={20} height={20} /> )} </div> </div> </div> ) }