Cara Buat Dark Mode di Next.js 13 dengan Tailwind CSS
Tags: nextjs, tailwindcss, tutorial, indonesia
Published: 2023-11-26 13:58:00

Dark mode adalah salah satu fitur yang sering kita temui di website, fungsi nya untuk memberikan pengguna kenyamanan membaca dan pengalaman yang unik.

Di artikel ini saya akan sharing bagaimana cara membuat dark mode di Next.js dengan Tailwind CSS.

Disini saya anggap pembaca semua sudah tau ya cara membuat project dengan Next.js dan sudah menginstall Tailwind CSS, jika belum, teman-teman dev bisa coba membuat project dengan panduan [Next.js Getting Started](https://nextjs.org/docs/getting-started/installation)

### Aktifkan Dark Mode di Tailwind

Langkah pertama adalah mengaktifkan dark mode di Tailwind pada file `**tailwind.config.js**`, tambahkan baris kode berikut ini:

```jsx
darkMode: 'class',
```

Sehingga kode terlihat seperti berikut:

```jsx
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx}",
    "./src/components/**/*.{js,ts,jsx,tsx}",
    "./src/app/**/*.{js,ts,jsx,tsx}",
  ],
  darkMode: "class",
  theme: {
    extend: {
      backgroundImage: {
        "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
        "gradient-conic":
          "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
      },
    },
  },
  plugins: [],
};
```

Dengan cara ini, kita dapat mengubah nilai class dengan mudah. Misal awalnya kita menerapkan background color defaultnya adalah “bg-zinc-50” dan class untuk darkMode adalah “bg-zinc-500”, maka kode akan kita tulis seperti berikut ini:

```jsx
className="bg-zinc-50 dark:bg-zinc-900"
```

### Menulis Kode Dark Mode di Pages

Sebagai contoh di project Next.js, kita akan mencoba menuliskan kode DarkMode di `src/app/page.tsx`, maka ini contoh menulis kode class:

```jsx
export default function Home() {
  return (
    <main className="bg-zinc-50 dark:bg-zinc-900 flex min-h-screen items-center justify-center">
      <div className="max-w-xs mx-auto">
        <h1 className="text-lg text-center text-zinc-900 dark:text-zinc-100">
          Contoh Dark Mode
        </h1>

        <p className="text-sm text-center text-zinc-700 dark:text-zinc-100">
          This is an example of how to implement dark mode in a Next.js app.
        </p>
      </div>
    </main>
  );
}
```

### Modifikasi layout

Pada project Next.js 13, file layout berada di `src/app/layout.tsx`, di file ini kita menambahkan properti dark di dalam className, seperti berikut ini:

```jsx
import './globals.css'

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className="dark">
      <body>{children}</body>
    </html>
  )
}
```

### Membuat Komponen Toggle

Komponen toggle ini kita gunakan sebagai button untuk mengalihkan mode dark ke light atau sebaliknya.

Komponen toggle bisa kita buat di “src/components” misal dengan nama ToggleTheme.tsx

Berikut kode di dalam komponen ToggleTheme.tsx

```jsx
export default function ToggleTheme() {
  return (
    <button
      type="button"
      aria-label="Toggle dark mode"
      className="rounded-sm bg-zinc-900 px-2 py-1.5 dark:bg-zinc-100"
    >
      <span className="inline-block text-sm text-zinc-100 dark:hidden">
        Tema Dark Dong
      </span>
      <span className="hidden text-sm text-zinc-800 dark:inline-block">
        Tema Light Dong
      </span>
    </button>
  )
}
```

### Implementasi Cookies

Sebelum komponen Toggle dapat digunakan, kita coba implementasi cookies untuk mendapatkan preferensi tema yang sedang digunakan pengguna, jika pengguna menggunakan tema dark atau gelap, maka website kita otomatis menggunakan tema dark, begitu pula sebaliknya.

Untuk implementasi Cookies di Next.js, kita bisa menggunakan library yang bernama ***cookies-next***. Berikut ini cara install nya:

```jsx
npm install --save cookies-next
```

Setelah selesai install library cookies-next, kita bisa membuat file di dalam `src/utils` dengan nama `colorScheme.ts`

```jsx
import { getCookie, setCookie } from 'cookies-next'

export const getCurrentScheme = async () => {
  // The `getCookie` function is not available on the server, imagine that
  // we have to access the scheme while Next.js is rendering the `<RootLayout />`
  // component (this happens server side). We can use the `cookies` function
  // from the `next/headers` package to access the cookies from the request headers.
  if (typeof window === 'undefined') {
    return import('next/headers').then(({ cookies }) => {
      return cookies().has('scheme') ? cookies().get('scheme')?.value : 'light'
    })
  }

  return getCookie('scheme', { path: '/' })
}

export const toggleScheme = async () => {
  const scheme = await getCurrentScheme()

  const newScheme = scheme === 'dark' ? 'light' : 'dark'

  setCookie('scheme', newScheme, {
    path: '/',
  })

  return newScheme
}
```

Kode diatas berfungsi untuk mengelola skema tampilan (dark mode atau light mode) pada aplikasi Next.js dengan menggunakan cookie untuk menyimpan status skema yang dipilih oleh pengguna.

### Implementasi colorScheme.ts di komponen ToggleTheme.tsx

Setelah itu, kita coba import komponen colorScheme.ts kedalam komponen ToggleTheme.tsx

```jsx
import { toggleScheme } from '@/utils/colorScheme';
```

tambahkan function baru

```jsx
const toggle = async () => {
await toggleScheme();
};
```

lalu pada tag button, tambahkan properti ***onClick*** dan isi value dengan nama function diatas

```jsx
onClick={toggle}
```

dan jangan lupa tambahkan kode use client pada bagian atas komponen ToggleTheme.tsx yang menandakan file tersebut dieksekusi di sisi client. Disini juga kita gunakan useRouter untuk memperbaharui tampilan halaman.

```jsx
'use client'
```

kode sepenuhnya sebagai berikut:

```jsx
'use client'

import { toggleScheme } from '@/utils/colorScheme'
import { useRouter } from 'next/navigation'

export default function ColorSchemeToggleButton() {
  const router = useRouter()

  const toggle = async () => {
    await toggleScheme()
    router.refresh()
  }

  return (
    <button
      type="button"
      aria-label="Toggle dark mode"
      className="rounded-sm bg-zinc-900 px-2 py-1.5 dark:bg-zinc-100"
      onClick={toggle}
    >
      <span className="inline-block text-sm text-zinc-100 dark:hidden">
        Switch to Dark
      </span>
      <span className="hidden text-sm text-zinc-800 dark:inline-block">
        Switch to Light
      </span>
    </button>
  )
}
```

### Modifikasi File Layout

Kembali lagi ke file layout.tsx, kita perlu mengimport komponen colorScheme yang dibuat pada folder utils dan membuat konstanta baru untuk menyimpan hasil dari komponen colorScheme.

Kode yang diterapkan sebagai berikut:

```jsx
import './globals.css'
import { getCurrentScheme } from '@/utils/colorScheme'

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const scheme = await getCurrentScheme()

  return (
    <html lang="en" className={scheme === 'dark' ? 'dark' : ''}>
      <body>{children}</body>
    </html>
  )
}
```

### Import ToggleTheme ke dalam pages

Setelah semua proses modifikasi dilakukan, kita coba import komponen ToggleTheme ke dalam pages.tsx

```jsx
import ToggleTheme from '@/components/ToggleTheme '

export default function Home() {
  return (
    <main className="flex min-h-screen items-center justify-center bg-zinc-50 dark:bg-zinc-900">
      <div className="mx-auto max-w-xs">
        <h1 className="text-center text-lg text-zinc-900 dark:text-zinc-100">
          Contoh Dark Mode
        </h1>

        <p className="text-center text-sm text-zinc-700 dark:text-zinc-100">
          This is an example of how to implement dark mode in a Next.js app.
        </p>
      </div>
    </main>
  )
}
```

Oke selesai, kita sudah berhasil implementasi Dark Mode di Next.js dengan Tailwind CSS.