Komponen dasar dari dua bagian pertama kini dirangkai menjadi komponen komposit: kartu yang menampung badge dan tombol, navigation bar yang membungkus logo dan menu, serta tab untuk berpindah section dokumentasi. Inilah pola kerja utama sebuah component library — komponen baru hampir selalu komposisi dari komponen lama, ditambah satu atau dua keputusan layout. Kita juga menyiapkan grid galeri yang dipakai Bagian 4 untuk memajang kartu komponen di halaman dokumentasi.
Tujuan Bagian dan Prasyarat #
Target bagian ini pada styles/komponen.css:
.carddengan elemen pendamping.card-badan,.card-judul,.card-teks, dan.card-aksi, plus varian.card-shadow.- Navigation:
.navbardenganposition: sticky,.nav-brand,.nav-menu, dan.nav-tautan. - Tab:
.tabs,.tab, dan.tab-aktifdengan garis bawah 2px yang tidak menggeser layout. .grid-kartu: grid tiga kolom dengan kartu selebar 288px pada wadah 960px.
Konsep layoutnya bersumber dari Flex Container dan Items , Card Grid , dan Sticky Header . Penataan kelas mengikuti prinsip Component-Based CSS , dengan penamaan dua tingkat yang dibedah di akhir bagian.
Kartu Konten #
Kartu memakai flex-direction: column agar elemen aksi selalu menempel di dasar ketika kartu diregangkan oleh grid, dan overflow: hidden agar sudut membulat memotong isi:
.card {
display: flex;
flex-direction: column;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
overflow: hidden;
}
.card-shadow {
box-shadow: var(--shadow-md);
}
.card-badan {
display: grid;
row-gap: var(--space-2);
padding: var(--space-6);
}
.card-judul {
font-size: var(--text-lg);
font-weight: 600;
color: var(--color-text);
}
.card-teks {
font-size: var(--text-sm);
line-height: 1.5;
color: var(--color-muted);
}
.card-aksi {
display: flex;
column-gap: var(--space-2);
margin-top: var(--space-2);
}Kartu contoh merangkai badge dari Bagian 1 dan tombol dari Bagian 2:
<article class="card card-shadow">
<div class="card-badan">
<span class="badge">Komponen</span>
<h3 class="card-judul">Button</h3>
<p class="card-teks">Tiga varian warna dan dua ukuran, lengkap dengan status disabled.</p>
<div class="card-aksi">
<button class="btn btn-kedua btn-kecil">Lihat Detail</button>
</div>
</div>
</article>Hasil di Browser:
Kartu berlatar rgb(255, 255, 255) dengan border rgb(228, 228, 231)
dan radius 10px; badan kartu berpadding 24px dengan jarak antar
elemen 8px. Judul terukur 20px dengan ketebalan 600, teks
penjelas 14px berwarna rgb(82, 82, 91).Navigation Bar dan Tab #
Navigation bar menempel di atas halaman lewat position: sticky, sementara tab memakai trik garis bawah transparan agar tinggi tab aktif dan pasif selalu sama:
.navbar {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
column-gap: var(--space-4);
padding: var(--space-3) var(--space-6);
background-color: var(--color-surface);
border-bottom: 1px solid var(--color-border);
}
.nav-brand {
display: inline-flex;
align-items: center;
column-gap: var(--space-2);
font-size: var(--text-lg);
font-weight: 700;
color: var(--color-text);
text-decoration: none;
}
.nav-menu {
display: flex;
column-gap: var(--space-6);
list-style: none;
}
.nav-tautan {
color: var(--color-muted);
font-weight: 500;
text-decoration: none;
}
.nav-tautan:hover {
color: var(--color-primary);
}
.tabs {
display: flex;
column-gap: var(--space-2);
border-bottom: 1px solid var(--color-border);
}
.tab {
padding: var(--space-2) var(--space-3);
font: inherit;
font-size: var(--text-sm);
font-weight: 500;
color: var(--color-muted);
background-color: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
}
.tab-aktif {
color: var(--color-primary);
border-bottom-color: var(--color-primary);
}<header class="navbar">
<a class="nav-brand" href="#">
<img src="assets/logo-komponen.svg" width="24" height="24" alt="">
Rakit UI
</a>
<nav>
<ul class="nav-menu">
<li><a class="nav-tautan" href="#komponen">Komponen</a></li>
<li><a class="nav-tautan" href="#token">Token</a></li>
</ul>
</nav>
</header>
<div class="tabs" role="tablist">
<button class="tab tab-aktif" role="tab">Buttons</button>
<button class="tab" role="tab">Inputs</button>
</div>Grid Galeri Komponen #
Halaman dokumentasi memajang kartu komponen dalam grid tiga kolom; Bagian 4 mengisinya dengan kartu nyata:
.grid-kartu {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-6);
margin-top: var(--space-6);
}Bedah Keputusan Layout #
position: stickydengantop: 0danz-index: 100: navbar mengalir dalam dokumen namun menempel saat digulir;z-indextinggi menjaga navbar berada di atas kartu dan badge. Perbedaannya denganfixeddibahas di chapter Sticky Header.overflow: hiddenpada.card: tanpa properti ini, konten yang menonjol — misalnya gambar header — menembus sudut membulat kartu. Dengan radius di kartu induk, isi cukup dipotong oleh kartu itu sendiri.- Garis bawah transparan pada
.tab: tab pasif tetap membawaborder-bottom: 2px solid transparent, sehingga saat kelas.tab-aktifmemunculkan garis primer, tinggi tab tidak berubah sedikit pun. Ini pencegahan layout shift paling murah. - Matematika
.grid-kartu: wadah 960px dikurangi padding 24px dua sisi menyisakan 912px; dua gap 24px memakan 48px; sisa 864px dibagi tiga kolom1frmenghasilkan kartu selebar 288px — angka yang diverifikasi probe. - Penamaan dua tingkat: pola
<blok>-<elemen>(.card-badan,.nav-menu) dipilih agar keterbacaan tetap tinggi tanpa penuh garis bawah ganda; varian BEM penuh (card__badan) diulas tersendiri pada chapter BEM .
Uji Bagian Ini #
Halaman uji bagian ini tersedia di /tests/css/proyek/component-library/cards-dan-navigation.html
, dengan spesifikasi lengkap pada tests/cards-dan-navigation.spec.js:
| Elemen | Properti | Diharapkan |
|---|---|---|
.navbar | position | sticky |
.navbar | top | 0px |
.navbar | z-index | 100 |
.nav-menu | column-gap | 24px |
.card | background-color | rgb(255, 255, 255) |
.card | border-radius | 10px |
.card-badan | padding-top | 24px |
.card-badan | row-gap | 8px |
.card-judul | font-size | 20px |
.card-teks | color | rgb(82, 82, 91) |
.tab-aktif | border-bottom-width | 2px |
.tab-aktif | color | rgb(13, 148, 136) |
.kartu-galeri | width | 288px |
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
styles/komponen.css
Unduh berkas/* =========================================================
Proyek: Component Library (Rakit UI) — styles/komponen.css
File utuh library yang berkembang mengikuti empat bagian:
Bagian 1 (Design Tokens), Bagian 2 (Buttons dan Inputs),
Bagian 3 (Cards dan Navigation), Bagian 4 (Themes dan
Documentation). Komentar "Bagian N" menandai kelompok
aturan yang dibahas pada setiap bagian.
========================================================= */
/* Bagian 1: Design Tokens --------------------------------- */
:root {
/* Token primitif: skala netral zinc */
--zinc-50: #fafafa;
--zinc-100: #f4f4f5;
--zinc-200: #e4e4e7;
--zinc-400: #a1a1aa;
--zinc-500: #71717a;
--zinc-600: #52525b;
--zinc-700: #3f3f46;
--zinc-800: #27272a;
--zinc-900: #18181b;
/* Token primitif: skala teal untuk warna primer */
--teal-500: #14b8a6;
--teal-600: #0d9488;
--teal-700: #0f766e;
/* Token primitif: warna status */
--hijau-600: #16a34a;
--merah-600: #dc2626;
/* Token semantik: peran, bukan warna */
--color-bg: #fafafa;
--color-surface: #ffffff;
--color-text: #18181b;
--color-muted: #52525b;
--color-border: #e4e4e7;
--color-primary: #0d9488;
--color-primary-hover: #0f766e;
--color-on-primary: #ffffff;
--color-primary-soft: rgb(13 148 136 / 10%);
--color-success: #16a34a;
--color-danger: #dc2626;
/* Skala spasi (kelipatan 4px) */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
/* Radius */
--radius-sm: 6px;
--radius-md: 10px;
--radius-full: 999px;
/* Bayangan */
--shadow-sm: 0 1px 2px rgb(0 0 0 / 6%);
--shadow-md: 0 4px 12px rgb(0 0 0 / 10%);
/* Tipografi */
--font-sans: system-ui, sans-serif;
--font-mono: ui-monospace, monospace;
--text-xs: 12px;
--text-sm: 14px;
--text-base: 16px;
--text-lg: 20px;
--text-xl: 24px;
}
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-sans);
font-size: var(--text-base);
line-height: 1.5;
color: var(--color-text);
background-color: var(--color-bg);
}
.wadah {
max-width: 960px;
margin: 0 auto;
padding: var(--space-6);
}
.badge {
display: inline-flex;
align-items: center;
column-gap: var(--space-1);
padding: var(--space-1) var(--space-2);
border-radius: var(--radius-full);
background-color: var(--color-primary-soft);
color: var(--color-primary);
font-size: var(--text-sm);
font-weight: 500;
}
/* Bagian 2: Buttons dan Inputs ---------------------------- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
column-gap: var(--space-2);
padding: var(--space-2) var(--space-4);
font: inherit;
font-size: var(--text-base);
font-weight: 500;
border: 1px solid transparent;
border-radius: var(--radius-md);
cursor: pointer;
text-decoration: none;
transition: background-color 150ms ease, border-color 150ms ease,
color 150ms ease;
}
.btn-primer {
background-color: var(--color-primary);
color: var(--color-on-primary);
}
.btn-primer:hover {
background-color: var(--color-primary-hover);
}
.btn-kedua {
background-color: var(--color-surface);
color: var(--color-text);
border-color: var(--color-border);
}
.btn-hantu {
background-color: transparent;
color: var(--color-primary);
}
.btn-kecil {
padding: var(--space-1) var(--space-3);
font-size: var(--text-sm);
}
.btn-besar {
padding: var(--space-3) var(--space-6);
font-size: var(--text-lg);
}
.btn:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.field {
display: grid;
row-gap: var(--space-2);
margin-bottom: var(--space-4);
}
.label {
font-size: var(--text-sm);
font-weight: 500;
}
.input {
width: 100%;
padding: var(--space-2) var(--space-3);
font: inherit;
color: var(--color-text);
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
}
.input:focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
border-color: var(--color-primary);
}
.input:disabled {
background-color: var(--color-bg);
color: var(--color-muted);
cursor: not-allowed;
}
.input-sukses {
border-color: var(--color-success);
}
.input-galat {
border-color: var(--color-danger);
}
.hint {
font-size: var(--text-xs);
color: var(--color-muted);
}
.hint-galat {
color: var(--color-danger);
}
/* Bagian 3: Cards dan Navigation -------------------------- */
.navbar {
position: sticky;
top: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
column-gap: var(--space-4);
padding: var(--space-3) var(--space-6);
background-color: var(--color-surface);
border-bottom: 1px solid var(--color-border);
}
.nav-brand {
display: inline-flex;
align-items: center;
column-gap: var(--space-2);
font-size: var(--text-lg);
font-weight: 700;
color: var(--color-text);
text-decoration: none;
}
.nav-menu {
display: flex;
column-gap: var(--space-6);
list-style: none;
}
.nav-tautan {
color: var(--color-muted);
font-weight: 500;
text-decoration: none;
}
.nav-tautan:hover {
color: var(--color-primary);
}
.tabs {
display: flex;
column-gap: var(--space-2);
border-bottom: 1px solid var(--color-border);
}
.tab {
padding: var(--space-2) var(--space-3);
font: inherit;
font-size: var(--text-sm);
font-weight: 500;
color: var(--color-muted);
background-color: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
}
.tab-aktif {
color: var(--color-primary);
border-bottom-color: var(--color-primary);
}
.grid-kartu {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-6);
margin-top: var(--space-6);
}
.card {
display: flex;
flex-direction: column;
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
overflow: hidden;
}
.card-shadow {
box-shadow: var(--shadow-md);
}
.card-badan {
display: grid;
row-gap: var(--space-2);
padding: var(--space-6);
}
.card-judul {
font-size: var(--text-lg);
font-weight: 600;
color: var(--color-text);
}
.card-teks {
font-size: var(--text-sm);
line-height: 1.5;
color: var(--color-muted);
}
.card-aksi {
display: flex;
column-gap: var(--space-2);
margin-top: var(--space-2);
}
/* Bagian 4: Themes dan Documentation ---------------------- */
[data-theme="gelap"] {
--color-bg: #18181b;
--color-surface: #27272a;
--color-text: #fafafa;
--color-muted: #a1a1aa;
--color-border: #3f3f46;
--color-primary-soft: rgb(20 184 166 / 16%);
--shadow-md: 0 4px 12px rgb(0 0 0 / 40%);
}
.tema-sampel {
padding: var(--space-6);
background-color: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
}
.docs-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: var(--space-4);
margin-top: var(--space-4);
}
.swatch {
display: block;
width: 64px;
height: 40px;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
}
.swatch-nama {
font-family: var(--font-mono);
font-size: var(--text-xs);
color: var(--color-muted);
}
.contoh-kode {
padding: var(--space-3) var(--space-4);
background-color: var(--zinc-900);
color: var(--zinc-200);
font-family: var(--font-mono);
font-size: var(--text-sm);
border-radius: var(--radius-md);
overflow-x: auto;
}
tests/buttons-dan-inputs.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 2: Buttons dan Inputs
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
// /tests/css/proyek/component-library/buttons-dan-inputs.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// .btn-primer: geometri dari kelas dasar, warna dari token semantik.
{ elemen: ".btn-primer", properti: "background-color", diharapkan: "rgb(13, 148, 136)" },
{ elemen: ".btn-primer", properti: "color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".btn-primer", properti: "padding-top", diharapkan: "8px" },
{ elemen: ".btn-primer", properti: "padding-left", diharapkan: "16px" },
{ elemen: ".btn-primer", properti: "border-radius", diharapkan: "10px" },
{ elemen: ".btn-primer", properti: "font-weight", diharapkan: "500" },
// .btn-besar: ukuran menimpa padding dan font-size kelas dasar.
{ elemen: ".btn-besar", properti: "font-size", diharapkan: "20px" },
{ elemen: ".btn-besar", properti: "padding-top", diharapkan: "12px" },
// .btn-kedua: permukaan putih dengan border dari token garis.
{ elemen: ".btn-kedua", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".btn-kedua", properti: "color", diharapkan: "rgb(24, 24, 27)" },
{ elemen: ".btn-kedua", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
// .btn:disabled: pseudo-class pada tombol dengan atribut disabled.
{ elemen: "button.btn[disabled]", properti: "opacity", diharapkan: "0.55" },
{ elemen: "button.btn[disabled]", properti: "cursor", diharapkan: "not-allowed" },
// .input: border, radius, dan tipografi dari token.
{ elemen: ".input", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
{ elemen: ".input", properti: "border-radius", diharapkan: "6px" },
{ elemen: ".input", properti: "font-size", diharapkan: "16px" },
{ elemen: ".input", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
// .input-galat: border berganti ke warna bahaya.
{ elemen: ".input-galat", properti: "border-top-color", diharapkan: "rgb(220, 38, 38)" },
// .hint: teks bantu kecil dan redup.
{ elemen: ".hint", properti: "font-size", diharapkan: "12px" },
{ elemen: ".hint", properti: "color", diharapkan: "rgb(82, 82, 91)" },
// .field: grid dengan jarak baris 8px dan pemisah antar field 16px.
{ elemen: ".field", properti: "row-gap", diharapkan: "8px" },
{ elemen: ".field", properti: "margin-bottom", diharapkan: "16px" },
];
tests/cards-dan-navigation.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 3: Cards dan Navigation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
// /tests/css/proyek/component-library/cards-dan-navigation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// .navbar: menempel di atas halaman dengan z-index tinggi.
{ elemen: ".navbar", properti: "position", diharapkan: "sticky" },
{ elemen: ".navbar", properti: "top", diharapkan: "0px" },
{ elemen: ".navbar", properti: "z-index", diharapkan: "100" },
{ elemen: ".navbar", properti: "padding-top", diharapkan: "12px" },
{ elemen: ".navbar", properti: "column-gap", diharapkan: "16px" },
// .nav-menu: flex dengan jarak antar tautan dari token spasi.
{ elemen: ".nav-menu", properti: "display", diharapkan: "flex" },
{ elemen: ".nav-menu", properti: "column-gap", diharapkan: "24px" },
// .card: permukaan putih, border token, radius dari token bentuk.
{ elemen: ".card", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".card", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
{ elemen: ".card", properti: "border-radius", diharapkan: "10px" },
// .card-badan: padding token space-6, jarak baris token space-2.
{ elemen: ".card-badan", properti: "padding-top", diharapkan: "24px" },
{ elemen: ".card-badan", properti: "row-gap", diharapkan: "8px" },
// .card-judul dan .card-teks: tipografi dari token teks.
{ elemen: ".card-judul", properti: "font-size", diharapkan: "20px" },
{ elemen: ".card-judul", properti: "font-weight", diharapkan: "600" },
{ elemen: ".card-teks", properti: "font-size", diharapkan: "14px" },
{ elemen: ".card-teks", properti: "color", diharapkan: "rgb(82, 82, 91)" },
// .tab-aktif: garis bawah 2px primer di atas garis transparan.
{ elemen: ".tab-aktif", properti: "color", diharapkan: "rgb(13, 148, 136)" },
{ elemen: ".tab-aktif", properti: "border-bottom-width", diharapkan: "2px" },
{ elemen: ".tab-aktif", properti: "border-bottom-color", diharapkan: "rgb(13, 148, 136)" },
// .kartu-galeri: bukti perhitungan grid tiga kolom pada wadah 960px.
{ elemen: ".kartu-galeri", properti: "width", diharapkan: "288px" },
];
tests/design-tokens.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 1: Design Tokens
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
// /tests/css/proyek/component-library/design-tokens.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// Token tersimpan di :root (elemen html) dan terbaca apa adanya.
{ elemen: "html", properti: "--color-primary", diharapkan: "#0d9488" },
{ elemen: "html", properti: "--space-6", diharapkan: "24px" },
{ elemen: "html", properti: "--radius-md", diharapkan: "10px" },
{ elemen: "html", properti: "--text-base", diharapkan: "16px" },
// body mengonsumsi token semantik: latar zinc-50, teks zinc-900.
{ elemen: "body", properti: "background-color", diharapkan: "rgb(250, 250, 250)" },
{ elemen: "body", properti: "color", diharapkan: "rgb(24, 24, 27)" },
{ elemen: "body", properti: "font-size", diharapkan: "16px" },
// .wadah: lebar maksimum 960px dengan padding dari token spasi.
{ elemen: ".wadah", properti: "max-width", diharapkan: "960px" },
{ elemen: ".wadah", properti: "padding-top", diharapkan: "24px" },
// .badge: latar primer lunak, teks primer, bentuk pil dari token.
{ elemen: ".badge", properti: "background-color", diharapkan: "rgba(13, 148, 136, 0.1)" },
{ elemen: ".badge", properti: "color", diharapkan: "rgb(13, 148, 136)" },
{ elemen: ".badge", properti: "border-radius", diharapkan: "999px" },
{ elemen: ".badge", properti: "font-size", diharapkan: "14px" },
{ elemen: ".badge", properti: "padding-top", diharapkan: "4px" },
];
tests/themes-dan-documentation.spec.js
Unduh berkas// ============================================================
// Spesifikasi uji — Proyek: Component Library
// Bagian 4: Themes dan Documentation
// ============================================================
// Berkas ini merangkum asersi yang diverifikasi oleh harness
// pada halaman uji:
// /tests/css/proyek/component-library/themes-dan-documentation.html
// Setiap entri memasangkan elemen probe dengan properti CSS
// dan nilai computed yang diharapkan.
const asersi = [
// Tema terang tetap berlaku di luar wadah data-theme.
{ elemen: "body", properti: "background-color", diharapkan: "rgb(250, 250, 250)" },
{ elemen: ".kartu-terang", properti: "background-color", diharapkan: "rgb(255, 255, 255)" },
{ elemen: ".kartu-terang", properti: "border-top-color", diharapkan: "rgb(228, 228, 231)" },
// Wadah gelap: token semantik ditimpa, latar dan garis mengikuti.
{ elemen: ".tema-sampel", properti: "background-color", diharapkan: "rgb(24, 24, 27)" },
{ elemen: ".tema-sampel", properti: "padding-top", diharapkan: "24px" },
{ elemen: ".tema-sampel", properti: "border-top-color", diharapkan: "rgb(63, 63, 70)" },
// Komponen di dalam wadah gelap ikut berganti tanpa aturan baru.
{ elemen: ".kartu-gelap", properti: "background-color", diharapkan: "rgb(39, 39, 42)" },
{ elemen: ".teks-gelap", properti: "color", diharapkan: "rgb(161, 161, 170)" },
// Custom property terwariskan: badge gelap membaca surface baru.
{ elemen: ".badge-gelap", properti: "--color-surface", diharapkan: "#27272a" },
{ elemen: ".badge-gelap", properti: "background-color", diharapkan: "rgba(20, 184, 166, 0.16)" },
// Komponen dokumentasi: swatch token berukuran tetap.
{ elemen: ".swatch", properti: "width", diharapkan: "64px" },
{ elemen: ".swatch", properti: "height", diharapkan: "40px" },
{ elemen: ".swatch", properti: "border-radius", diharapkan: "6px" },
// .contoh-kode memakai primitif zinc: tetap gelap di kedua tema.
{ elemen: ".contoh-kode", properti: "background-color", diharapkan: "rgb(24, 24, 27)" },
{ elemen: ".contoh-kode", properti: "color", diharapkan: "rgb(228, 228, 231)" },
{ elemen: ".contoh-kode", properti: "font-size", diharapkan: "14px" },
{ elemen: ".contoh-kode", properti: "padding-top", diharapkan: "12px" },
{ elemen: ".contoh-kode", properti: "border-radius", diharapkan: "10px" },
];