Component Libraries — UI/UX

Component Library — Building Blocks yang Reusable Component library adalah kumpulan UI components yang sudah didesain dan dikodekan untuk digunakan ulang di…

Komponen adalah satu bagian UI (tombol, kolom isian, kartu kamar) yang didesain dan dikodekan sekali, dengan pilihan tampilan dan keadaan yang sudah ditentukan, lalu dipakai di mana-mana. Component library adalah kumpulan komponen itu beserta dokumentasinya. Bayangin perlengkapan kamar standar di homestay Bu Sri: tiap kamar dapat lampu baca, gantungan kunci, dan papan "Jangan diganggu" yang sama. Papannya punya dua sisi, lampunya punya dua ukuran. Kalau Bu Sri mengganti desain gantungan kunci, dia mengubah daftar perlengkapannya sekali, dan ketiga kamar ikut. Kalau tiap kamar membeli perlengkapannya sendiri-sendiri, setahun kemudian gak ada dua kamar yang sama.

🧪 Tebakan cepat: Kartu Kamar Loteng dan Kamar Kebun dulu disalin dari kartu Kamar Teras, lalu diubah sedikit. Hari ini Bu Sri menaikkan tombol di kartu Teras dari 40px ke 48px. Berapa dari tiga tombol "Pilih" yang sekarang 48px? Jawabannya ada di bagian "Satu sumber, banyak pemakaian".

Satu sumber, banyak pemakaian

Ini tiga kartu kamar yang dibuat dengan menyalin. Kami mengukur tinggi tombolnya dengan getBoundingClientRect() di Chromium, WebKit, dan Firefox, hasilnya sama:

Kartu Asalnya Tinggi tombol Yang lain
Kamar Teras yang baru diubah Bu Sri 48px
Kamar Loteng salinan, border: 0 38px hijaunya #16803d, salah ketik
Kamar Kebun salinan, padding: 8px 42px penuh, tapi tombolnya tetap hijau karena salinannya gak punya gaya :disabled

Jadi jawaban tebakannya: cuma satu. Itu jawaban tebakannya. Salinan gak tahu kalau aslinya berubah, dan tiap salinan pelan-pelan menjauh. Ini disebut drift.

Komponen membalik arahnya: satu sumber, banyak pemakaian. Di JavaScript biasa, komponen bisa berupa fungsi yang menerima data dan mengembalikan markup:

<div class="rooms" id="rooms"></div>

<script>
  function roomCard({ name, price, guests, status = "tersedia" }) {
    const harga = "Rp " + price.toLocaleString("id-ID");   // 350000 jadi "Rp 350.000"
    let aksi = `<button type="button" class="btn btn--primary btn--lg">Pilih ${name}</button>`;
    if (status === "penuh") aksi = `<button type="button" class="btn btn--secondary btn--lg" disabled>Penuh 12 Des</button>`;
    return `<article class="room-card room-card--${status}">
      <h2>${name}</h2>
      <p>${harga} / malam · ${guests} tamu</p>
      ${aksi}
    </article>`;
  }

  document.querySelector("#rooms").innerHTML = [
    roomCard({ name: "Kamar Teras", price: 350000, guests: 2 }),
    roomCard({ name: "Kamar Loteng", price: 275000, guests: 2 }),
    roomCard({ name: "Kamar Kebun", price: 425000, guests: 4, status: "penuh" }),
  ].join("");
</script>

Anatomi: variants, states, sizes, props

Tiap komponen di library perlu empat hal: variants (versi tampilannya), states (keadaannya saat dipakai), sizes (ukurannya), dan props (masukan yang boleh diatur pemakainya). Ini ketiga komponen halaman Bu Sri:

Tombol .btn Kolom isian .field Kartu kamar .room-card
Variants primary, secondary, ghost text, tel, email tersedia, terpilih, penuh
Sizes sm 32px, md 40px, lg 48px satu: 44px ringkas, dengan foto
States default, hover, active, focus-visible, disabled, loading default, focus, invalid, disabled loading (skeleton), default, foto gagal dimuat
Props label, variant, size, disabled, busy label, type, help, error, disabled name, price, guests, status

Di HTML dan CSS biasa, "API" komponen adalah class dan atributnya:

.btn { padding: 7px 16px; font: inherit; font-weight: 600; line-height: 24px; border: 1px solid transparent; border-radius: var(--radius-md); }
.btn--sm { padding: 3px 12px; font-size: 14px; }  /* 32px */
.btn--lg { padding: 11px 16px; }                  /* 48px */
.btn--primary   { color: var(--on-action); background: var(--action); }
.btn--secondary { color: var(--action); background: var(--surface-card); border-color: var(--action); }
.btn--ghost     { color: var(--action); background: transparent; }
.btn:focus-visible { outline: 3px solid var(--text); outline-offset: 2px; }
.btn:disabled { color: var(--text-muted); background: var(--border); border-color: var(--border); cursor: not-allowed; }
.btn[aria-busy="true"] { cursor: progress; }

Dokumentasi komponen

Komponen tanpa dokumentasi akan dipakai salah, atau disalin lagi. Satu halaman dokumentasi berisi:

  1. Kegunaan: kapan dipakai, kapan jangan. "Kartu kamar untuk daftar kamar; jangan untuk ringkasan pesanan."
  2. Variants, sizes, dan states, masing-masing dengan contoh yang bisa dilihat.
  3. Tabel props, seperti ini untuk roomCard:
Prop Tipe Default Catatan
name string wajib boleh panjang: judulnya turun ke baris baru
price number wajib per malam: 350000 ditulis "Rp 350.000"
guests number wajib jumlah tamu maksimal
status "tersedia", "terpilih", "penuh" "tersedia" penuh: tombol nonaktif dan tanggal kosong berikutnya
  1. Catatan aksesibilitas: label tombolnya menyebut nama kamar ("Pilih Kamar Teras"), supaya tiga tombol bisa dibedakan saat dibacakan screen reader.
  2. Contoh kode yang bisa disalin.

Banyak tim menulisnya di Storybook, "a frontend workshop for building UI components and pages in isolation". Tiap story adalah satu keadaan komponen: tombol primary lg loading, kolom tel invalid. Lab di halaman ini bekerja dengan cara yang sama.

Pakai library atau bikin sendiri

Jenis Contoh Yang kamu dapat Yang kamu kerjakan
Library lengkap Material UI, Ant Design tampilan dan perilaku jadi menyesuaikan dengan brand, sering melawan gaya bawaannya
Library headless Radix Primitives, React Aria, Headless UI perilaku: keyboard, fokus, atribut ARIA semua CSS-nya
Kode yang disalin ke proyek shadcn/ui kode komponen masuk ke folder proyekmu lewat npx shadcn@latest add button merawat kode itu sendiri

shadcn/ui menulis tentang dirinya: "This is not a component library. It is how you build your component library." Kodenya jadi milikmu.

Cara memilih untuk situs Bu Sri:

⚠️ Jebakan yang sering ketemu

TL;DR: Komponen adalah satu bagian UI yang dibuat sekali dan dipakai di mana-mana; component library adalah kumpulannya plus dokumentasi. Salinan tangan menjauh (drift: tombol 48, 38, 42px), komponen membuat satu perubahan sampai ke semua pemakai. Tiap komponen punya empat hal: variants (primary, secondary, ghost), states (default, hover, active, focus-visible, disabled, loading), sizes (sm 32, md 40, lg 48px), dan props (masukannya, misalnya name, price, guests, status). Dokumentasikan kegunaan, variants dan states, tabel props, catatan aksesibilitas, dan contoh kode, misalnya di Storybook (satu story = satu keadaan). Pakai elemen HTML bawaan dulu (<button>, <dialog>), library headless (Radix Primitives, React Aria, Headless UI) untuk perilaku rumit seperti date picker, library lengkap (Material UI, Ant Design) untuk alat internal, dan shadcn/ui kalau ingin kode komponennya jadi milikmu.

Yang akan kamu pelajari