Lompat ke konten
dokumentasi.id
Commit 9a47d33
v2
Star3,4 rb

8

Styling, Token Warna, dan Tema

src/styles/globals.css adalah stylesheet global utama. Berkas itu mengimpor tailwindcss dan plugin @tailwindcss/forms, lalu menaruh seluruh token desain di dalam blok @theme. src/styles/globals.css:1-2 Berkas kedua, src/styles/colors.css, bukan stylesheet umum: isinya hanya preset palet primary untuk keperluan demo pergantian warna, dan baris pertamanya meminta berkas itu dihapus setelah warna yang diinginkan disalin. src/styles/colors.css:1-15

Pipeline CSS dari @theme sampai kelas utilitas

Tailwind di repository ini dikonfigurasi sepenuhnya lewat CSS; tidak ada tailwind.config.js. Kedua berkas stylesheet masuk ke PostCSS dengan dua plugin, @tailwindcss/postcss dan autoprefixer. postcss.config.js:1-6 Alur dari berkas sumber sampai CSS final terlihat pada diagram berikut.

graph LR
  G["src/styles/globals.css"] --> PC["postcss.config.js"]
  C["src/styles/colors.css"] --> PC
  PC --> TW["@tailwindcss/postcss"]
  PC --> AP["autoprefixer"]
  TW --> OUT["CSS final"]
  style G fill:#336791,color:#fff
  style C fill:#336791,color:#fff
  style PC fill:#f59e0b,color:#000
  style TW fill:#8b5cf6,color:#fff
  style AP fill:#8b5cf6,color:#fff
  style OUT fill:#2d7d46,color:#fff
%% fig: Rantai PostCSS untuk dua berkas stylesheet
%% desc: globals.css dan colors.css diolah @tailwindcss/postcss lalu autoprefixer, dan keluar sebagai satu CSS final.
Fig. 1: Rantai PostCSS untuk dua berkas stylesheetglobals.css dan colors.css diolah @tailwindcss/postcss lalu autoprefixer, dan keluar sebagai satu CSS final.

Urutan impor ditentukan di root layout: globals.css lebih dulu, lalu colors.css dengan komentar !STARTERCONF yang meminta impor demo itu segera dihapus. src/app/layout.tsx:4-6 Layout segmen komponen mengimpor colors.css sendiri tanpa globals.css. src/app/components/layout.tsx:4

Token di dalam blok @theme

Satu blok @theme memuat semua variabel yang dipakai lintas komponen: font, palet primary 11 langkah, satu warna gelap, dan dua animasi. src/styles/globals.css:4-27

TokenNilaiPemakai nyata
--font-primary'Inter', system-ui, sans-serifkelas .h0 sampai .p lewat font-primary
--color-primary-50 … --color-primary-95011 langkah oklch dengan hue 213.79bg-primary-*, text-primary-*, ring-primary-*
--color-dark#222222bg-dark pada halaman komponen dan variant light Button
--animate-flickerflicker 3s linear infiniteikon peringatan di error.tsx dan not-found.tsx
--animate-shimmershimmer 1.3s linear infiniteSkeleton

Setiap variabel warna di @theme langsung menjadi kelas utilitas. Buktinya ada di komponen: variant primary pada Button memakai bg-primary-500, border-primary-600, hover:bg-primary-600, dan active:bg-primary-700. src/components/buttons/Button.tsx:61-67 UnderlineLink memakai focus-visible:ring-primary-500 bersama border-dark. src/components/links/UnderlineLink.tsx:16-18 Pemetaan variant Button ke token terlihat di tabel ini.

Variant ButtonKelas warnaSumber token
primarybg-primary-500 text-white, border-primary-600--color-primary-500, --color-primary-600
outlinetext-primary-500, border-primary-500, hover:bg-primary-50--color-primary-50, --color-primary-500
ghosttext-primary-500, hover:bg-primary-50--color-primary-50, --color-primary-500
lightbg-white text-gray-700, hover:text-dark--color-dark
darkbg-gray-900 text-white, border-gray-600palet bawaan Tailwind

Rincian katalog komponen ada di Katalog Komponen Pratinjau, dengan pembahasan terpisah di Komponen Tombol dan Komponen Link.

Animasi dan keyframes

Dua token animasi ditopang oleh dua @keyframes di berkas yang sama. flicker menurunkan opacity ke 0.4 dan melepas drop-shadow pada persentase tertentu dari siklus 3 detik, sedangkan shimmer menggeser background-position dari -700px ke 700px. src/styles/globals.css:30-62

Konsumsi keduanya nyata di tiga tempat. Ikon RiAlarmWarningFill di halaman error dan halaman 404 memakai drop-shadow-glow animate-flicker text-red-500. src/app/error.tsx:24-26 src/app/not-found.tsx:14-16 Skeleton memakai animate-shimmer bersama backgroundImage linear-gradient dan backgroundSize: '700px 100%', yang cocok dengan jarak geser keyframe shimmer. src/components/Skeleton.tsx:7-19

⚠️ Kelas drop-shadow-glow tidak didefinisikan di src/styles/globals.css. Hanya animate-flicker yang punya token di @theme, jadi bagian glow dari ikon peringatan tidak berasal dari stylesheet repository ini.

Tipografi dan kelas layout di @layer base

@layer base menampung @font-face Inter dari /fonts/inter-var-latin.woff2 dengan font-display: block, kursor khusus .cursor-newtab, seluruh aturan tipografi, dan dua kelas layout. src/styles/globals.css:64-126 Skala tipografi memakai @apply sehingga ukuran naik pada breakpoint md.

SelektorAturan @apply
.h0font-primary text-3xl font-bold md:text-5xl
h1, .h1font-primary text-2xl font-bold md:text-4xl
h2, .h2font-primary text-xl font-bold md:text-3xl
h3, .h3font-primary text-lg font-bold md:text-2xl
h4, .h4font-primary text-base font-bold md:text-lg
body, .pfont-primary text-sm md:text-base

Kelas .h0 sampai .p itu menempel langsung pada elemen h1–h4 dan body, jadi ukuran judul sudah berlaku tanpa kelas tambahan. src/styles/globals.css:81-110 Di bagian yang sama ada .layout dengan max-width: 68.75rem, .min-h-main dengan min-h-[calc(100vh-56px)], dan penyesuaian .bg-dark a.custom-link. src/styles/globals.css:112-125

Utilitas animated-underline

@layer utilities hanya berisi satu kelas, .animated-underline. Kelas itu menyusun dua lapis linear-gradient: lapis pertama transparan sebagai penahan ruang, lapis kedua bergradasi dari var(--color-primary-400) ke var(--color-primary-500). background-size dimulai dari 100% 2px, 0 2px dan berubah menjadi 0 2px, 100% 2px saat :hover atau :focus-visible, dengan transition: 0.3s ease yang dibungkus prefers-reduced-motion: no-preference. src/styles/globals.css:128-151 Karena memakai var(--color-primary-*) secara langsung, garis bawah ini ikut berubah ketika palet primary diganti.

Demo pergantian palet dari colors.css

src/styles/colors.css mendefinisikan ulang --color-primary-50 sampai --color-primary-950 di dalam kelas bernama sesuai palet Tailwind, misalnya .slate dan .rose sebagai blok terakhir. src/styles/colors.css:296-308 Mekanisme demo bergantung pada sifat inherit variabel CSS: kelas palet dipasang pada elemen section, sehingga semua utilitas bg-primary-* di dalam subtree itu membaca nilai baru.

graph TD
  LIST["colorList: 22 nama palet"] --> SEL["select onChange setColor"]
  SEL --> SEC["section dengan kelas mode dan nama palet"]
  SEC --> VAR["--color-primary-* di subtree section"]
  VAR --> SW["bg-primary-50 sampai bg-primary-950"]
  SW --> VIS["kotak swatch berganti warna"]
  style LIST fill:#8b5cf6,color:#fff
  style SEL fill:#f59e0b,color:#000
  style SEC fill:#2d7d46,color:#fff
  style VAR fill:#336791,color:#fff
  style SW fill:#2d7d46,color:#fff
  style VIS fill:#2d7d46,color:#fff
%% fig: Alur pergantian palet primary pada halaman komponen
%% desc: Nama palet dari colorList menjadi kelas pada section, variabel primary di subtree berubah, dan utilitas bg-primary-* ikut berganti.
Fig. 2: Alur pergantian palet primary pada halaman komponenNama palet dari colorList menjadi kelas pada section, variabel primary di subtree berubah, dan utilitas bg-primary-* ikut berganti.

Halaman pratinjau menyimpan dua state: mode bertipe 'dark' | 'light' dengan nilai awal 'light', dan color bertipe turunan colorList dengan nilai awal 'sky'. src/app/components/page.tsx:25-29 Keduanya digabung pada satu section: kelas warna latar bg-dark atau bg-white, lalu nama palet sebagai kelas tambahan. src/app/components/page.tsx:39-40 Bagian "Customize Colors" memuat teks pengantar bahwa warna primary bisa diganti lewat globals.css, sebuah select dengan opsi dari colorList, dan tautan ke berkas colors.css di GitHub. src/app/components/page.tsx:64-68 Di bawah select itu ada 11 kotak bg-primary-50 sampai bg-primary-950 sebagai contoh skala penuh. src/app/components/page.tsx:93-127

colorList berisi 22 nama palet, dari slate sampai rose. src/app/components/page.tsx:438-461 Jumlah itu sepadan dengan jumlah blok kelas di colors.css: satu blok untuk setiap nama, ditutup .rose di baris 296. src/styles/colors.css:296-308

⚠️ colors.css adalah bahan demo, bukan bagian desain final. Impor di root layout ditandai !STARTERCONF untuk dihapus. src/app/layout.tsx:4-6 Jika berkas itu dihapus tanpa menyalin palet pilihan ke @theme, select pada halaman komponen tetap menampilkan 22 nama, tetapi kelas tersebut tidak lagi punya variabel sehingga 22 opsi itu tidak mengubah warna apa pun.

Tema gelap dan terang

Repository ini tidak memakai varian dark: Tailwind dan tidak membaca prefers-color-scheme. "Tema" di sini adalah state React pada halaman pratinjau: toggleMode membalik nilai mode antara 'dark' dan 'light'. src/app/components/page.tsx:25-29 Saat mode bernilai 'dark', section memakai bg-dark dan Button pemanggil toggle memakai variant='light'; saat 'light', latarnya bg-white dan tombolnya variant='dark'. Karena bg-dark berasal dari --color-dark: #222222, warna gelap itu ikut menjadi bagian dari token di @theme. src/styles/globals.css:4-27

Pemilihan latar berada di satu tempat saja, yaitu halaman komponen. Komponen lain menerima informasi tema lewat prop isDarkBg untuk menyesuaikan hover pada variant outline dan ghost, seperti terlihat pada Button. src/components/buttons/Button.tsx:61-67 Pola layout dan metadata yang membungkus halaman ini dibahas di App Router, Layout, dan Metadata.