Panduan implementasi dark mode dengan Claude Code
Dark mode dengan CSS variables, preferensi sistem, localStorage, hydration aman, dan aksesibilitas.
Mulai dari risiko produk
Panduan implementasi dark mode dengan Claude Code bukan sekadar meminta Claude Code membuat layar lebih menarik. Tujuannya adalah memperbaiki interface nyata tanpa merusak conversion, keterbacaan, aksesibilitas, dan tampilan mobile. Di produksi, empty state, loading, error, keyboard focus, teks panjang, slot iklan, code block, dan posisi CTA sangat menentukan.
Baca juga claude code design system, claude code accessibility, claude code code review. Referensi resmi: Claude Code docs, MDN prefers-color-scheme, MDN color-scheme, WCAG contrast. Prompt untuk Claude Code harus menjelaskan tujuan, batas perubahan, use case, pitfall, dan cara verifikasi.
Prompt yang disarankan
Implementasikan perbaikan ini dengan perubahan aman paling kecil.
Hormati komponen, design token, dan routing yang sudah ada.
Cakup use case, pitfall, aksesibilitas, tampilan mobile, dan failure state.
Kembalikan kode yang bisa disalin serta review checklist.
Use case checklist
- Landing page dan artikel, saat pembaca perlu menemukan langkah berikutnya tanpa merasa terganggu.
- Dashboard SaaS dengan loading, empty data, error, dan success state.
- Checkout, signup, dan konsultasi, saat tombol utama harus tetap jelas.
- Review tim, ketika Claude Code harus memberi kode sekaligus kriteria pengecekan.
Kode implementasi
:root {
color-scheme: light;
--color-page: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-muted: #475569;
--color-border: #dbe3ef;
--color-link: #2563eb;
--color-focus: #f59e0b;
}
[data-theme="dark"] {
color-scheme: dark;
--color-page: #0b1120;
--color-surface: #111827;
--color-text: #f8fafc;
--color-muted: #cbd5e1;
--color-border: #334155;
--color-link: #93c5fd;
--color-focus: #fbbf24;
}
body {
background: var(--color-page);
color: var(--color-text);
}
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
const storageKey = "theme";
const root = document.documentElement;
const stored = localStorage.getItem(storageKey);
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
root.dataset.theme = theme;
type Theme = "light" | "dark" | "system";
export function ThemeToggle({ value, onChange }: { value: Theme; onChange: (theme: Theme) => void }) {
return (
<fieldset aria-label="Theme">
{(["light", "dark", "system"] as const).map((theme) => (
<button
key={theme}
type="button"
aria-pressed={value === theme}
onClick={() => onChange(theme)}
>
{theme}
</button>
))}
</fieldset>
);
}
Cegah kedip tema (warna salah sekejap di awal)
Pitfall pertama pada dark mode adalah “kedip”: sekejap layar terang terlihat saat membuka halaman, lalu berubah gelap. Dalam bahasa Inggris disebut FOUC (Flash of Unstyled Content) atau theme flash. Penyebabnya, tema baru diganti dengan JavaScript setelah HTML tampil. Jika data-theme ditambahkan setelah menunggu CSS atau React dimuat, selama jeda itu warna awal (umumnya terang) sudah terlihat.
Solusinya, jalankan skrip sangat pendek penentu tema secara sinkron sebelum konten, di dalam <head>. Dengan begitu data-theme ditetapkan sebelum layar digambar, hanya berdasarkan setelan tersimpan dan setelan perangkat.
<script>
(function () {
var stored = localStorage.getItem("theme");
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
var theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
document.documentElement.dataset.theme = theme;
})();
</script>
Kuncinya, jaga skrip ini tetap ringan dan jalankan sebelum render konten. Jika proses berat atau inisialisasi React dimasukkan di sini, kedip akan kembali. Di Astro maupun Next.js, perlakukan skrip kecil ini secara terpisah agar tema bisa ditetapkan tanpa menunggu hydration framework (proses menambahkan interaktivitas di browser pada HTML yang dibuat di server). Karena server tidak tahu setelan perangkat, hormati setelan perangkat saat pertama, lalu saat pengguna mengganti, simpan ke localStorage dan utamakan di kunjungan berikutnya.
Buat kontras, gambar, dan bayangan tetap terbaca di mode gelap
Membalik warna saja tidak menyelesaikan dark mode. Kontras yang cukup di layar terang bisa jadi kurang di latar gelap. Targetkan rasio kontras teks terhadap latar minimal 4.5:1 sesuai WCAG. Teks pelengkap abu muda, placeholder, dan tombol nonaktif paling mudah jadi tidak terbaca di latar gelap.
Gambar dan bayangan juga perlu disesuaikan. Logo atau ikon yang dibuat dengan asumsi latar putih akan kehilangan tepinya di latar gelap. Untuk PNG transparan, beri warna latar atau siapkan versi khusus gelap. Bayangan yang efektif di latar terang nyaris tak terlihat di latar gelap, jadi batas yang mengandalkan bayangan sebaiknya dinyatakan ulang dengan garis seperti --color-border.
| Elemen | Asumsi di mode terang | Penyesuaian di mode gelap |
|---|---|---|
| Teks pelengkap | Abu muda sudah cukup | Naikkan kecerahan demi kontras |
| Logo/ikon | Berasumsi latar putih | Beri latar atau ganti versi gelap |
| Bayangan | Abu pekat menyatakan batas | Nyatakan ulang dengan garis (border) |
| Warna status | Hijau/merah cerah | Turunkan saturasi, sertakan ikon |
Saat menyuruh Claude Code mereview, minta ia mencari secara spesifik “bagian yang kontrasnya turun di latar gelap”, “gambar yang berasumsi putih”, dan “batas yang dinyatakan dengan bayangan” agar lebih sedikit yang terlewat.
Pitfall checklist
- Mengoptimalkan hanya untuk screenshot bisa merusak alur pengguna nyata.
- Mengandalkan warna atau gerakan saja akan menurunkan aksesibilitas.
- Tidak mengecek lebar 375px dapat membuat horizontal scroll.
- Mengabaikan data kosong, label panjang, jaringan lambat, dan reload memicu bug produksi.
- Membiarkan Claude Code mengubah file tidak terkait membuat review mahal.
Verifikasi
Setelah implementasi, minta Claude Code melakukan review pass terpisah. Minta daftar file berubah, risiko, browser check, dan manual check. Lalu buka mobile width dan cek overflow, scroll code block, CTA, focus style, dan teks bantuan.
Sudut monetisasi
Topik ini memengaruhi iklan, kartu produk, link konsultasi, tabel harga, dan lead form. Untuk menerapkannya di repository nyata, halaman training dan konsultasi Claude Code membantu membuat workflow berulang.
Catatan review tambahan
- Bandingkan screenshot sebelum/sesudah dan cek CTA, iklan, teks, form, dan code block.
- Tanyakan ke Claude Code apa yang bisa dihapus, nama apa yang tidak cocok, dan asumsi apa yang berisiko.
- Sebelum deploy, uji mobile, desktop, keyboard, jaringan lambat, data kosong, dan reload.
Hasil setelah saya mencoba langkah ini
Saya mengujinya dalam tiga langkah: implementasi, review, dan pengecekan mobile, dengan asumsi tidak merusak UI blog yang sudah ada, sambil melihat lebar 375px, tampilan normal, jaringan lambat, dan operasi keyboard. Diff lebih kecil daripada redesign besar, dan masalah layout serta aksesibilitas terlihat sebelum deploy. Tidak menyerahkan semuanya sekaligus ke Claude Code, melainkan membaginya menjadi implementasi, review, dan perbaikan, membuat diff lebih mudah dibaca dan kualitasnya lebih stabil.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Cara Menulis Instruksi agar Claude Code Hanya Mengubah Satu File
Dari kegagalan 'bikin lebih bagus' yang mengubah 40 baris: template brief Claude Code yang menyatukan scope, verifikasi, dan rollback.
Pulih dari permission denial Claude Code tanpa melemahkan guardrail
Ubah command Claude Code yang ditolak menjadi recovery prompt dengan alasan, alternatif aman, proof command, dan kriteria retry.
Claude Code Harness Smoke Test: loop bukti 15 menit sebelum mempercayai agen
Pemeriksaan Claude Code untuk scope, area terlarang, command bukti, URL publik, dan CTA pendapatan.