Loading...
Loading...
Loading...
วิธี setup dark/light mode ใน Next.js + Tailwind v4 — ตั้งแต่ install จนใช้งานได้
5 ขั้นตอน: install → @custom-variant → provider → layout → toggle
pnpm add next-themes/* globals.css */
@import 'tailwindcss';
@custom-variant dark (&:is(.dark *));// components/theme/theme-provider.tsx
'use client';
import { ThemeProvider as NextThemesProvider } from 'next-themes';
export function ThemeProvider({ children }: { children: React.ReactNode }) {
return (
<NextThemesProvider
attribute="class" // ใช้ class บน <html> สำหรับ toggle
defaultTheme="dark" // default เป็น dark
enableSystem={false} // ไม่ตาม system preference
disableTransitionOnChange // ป้องกัน flash ตอน toggle
>
{children}
</NextThemesProvider>
);
}// app/layout.tsx
import { ThemeProvider } from '@/components/theme/theme-provider';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
}
// สังเกต: layout ไม่ต้องส่ง props ให้ ThemeProvider
// เพราะ config ทั้งหมดอยู่ใน provider wrapper แล้ว
// → layout เป็น Server Component ได้สะอาดๆ// components/theme/theme-toggle.tsx
'use client';
import { Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { Button } from '@/components/ui/button';
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<Button
variant="outline"
size="icon"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
className="relative"
>
{/* Light mode: แสดง Moon, Dark mode: ซ่อน */}
<Moon className="h-[1.2rem] w-[1.2rem] transition-all dark:scale-0 dark:-rotate-90" />
{/* Light mode: ซ่อน, Dark mode: แสดง Sun */}
<Sun className="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
</Button>
);
}next-themes เพิ่ม class "dark" บน <html> → CSS variable เปลี่ยนค่า → สีทั้ง app เปลี่ยนอัตโนมัติ
:root {
--background: oklch(1 0 0); /* ขาว */
--foreground: oklch(0.145 0 0); /* ดำ */
--primary: oklch(0.205 0 0); /* ดำเข้ม */
--card: oklch(1 0 0); /* ขาว */
--muted: oklch(0.97 0 0); /* เทาอ่อน */
}.dark {
--background: oklch(0.145 0 0); /* ดำ */
--foreground: oklch(0.985 0 0); /* ขาว */
--primary: oklch(0.922 0 0); /* ขาวอ่อน */
--card: oklch(0.205 0 0); /* ดำอ่อน */
--muted: oklch(0.269 0 0); /* เทาเข้ม */
}<!-- Light mode -->
<html lang="en"> <!-- ไม่มี class dark -->
<!-- Dark mode — next-themes เพิ่ม class อัตโนมัติ -->
<html lang="en" class="dark">
<!-- Component ใช้ class เดิม — สีเปลี่ยนตาม CSS variable -->
<div className="bg-background text-foreground">
<!-- light: พื้นขาว ตัวอักษรดำ -->
<!-- dark: พื้นดำ ตัวอักษรขาว -->
</div>กดปุ่ม toggle แล้วดูทุก element เปลี่ยนสีทันที — ใช้ CSS variable เดียวกันทั้งหมด
text-foreground — ตัวอักษรหลัก
text-muted-foreground — ตัวอักษรรอง
text-primary — สีหลัก
text-destructive — สี error