Dokumentasi
Semua yang dipakai buat bikin app di *.hanif.app
Tiap bagian punya pratinjau hidup dan kode yang bisa disalin. Kalau ragu bentuknya, mulai dari bidang halaman.
Mulai
Tiga berkas, nol paket, nol build. Salin ke app, lalu tautkan. Kalau app-nya berjanji nggak manggil server lain, salin — jangan tautkan ke ui.hanif.app.
<link rel="stylesheet" href="/lib/ui.css"> <link rel="stylesheet" href="/lib/layout.css"> <script src="/lib/ui.js" type="module"></script>
Tiga aturan
Netral dulu
Bidang dan garis pakai hitam-putih. Warna baru muncul waktu ada yang perlu ditekan atau ditandai.
Satu warna penuh per layar
Kalau ada dua bidang warna besar, salah satunya pasti nggak penting.
Bentuk dulu, baru warna
Tentukan bidang halaman sebelum menyentuh palet.
Bidang halaman
Tiga watak. Pilih satu di awal, jangan dicampur dalam satu halaman.
| Kelas | Lebar | Buat apa |
|---|---|---|
.shell-wide | 1760 | Etalase, galeri, landing — kesan layar lega |
.shell-dash | 1560 | Dashboard: lebar, padat data, hiasan minim |
.shell-compact | 460 | App kecil: satu kolom tengah, rasa aplikasi HP |
<main class="shell-dash section-sm">
<div class="split">
<nav class="side">…</nav>
<div class="stack">…</div>
</div>
</main>
Warna
Tindakan utama, tautan, fokus
--blue #0040ffPerlu perhatian, tertunda
--orange #ff5c00Berhasil, aktif, naik
--green #00a63eGagal, hapus, turun
--red #ff2d2dPeringatan, sorotan
--yellow #ffc400Fitur baru, label khusus
--purple #6d28ffTiap warna bawa pasangan teksnya sendiri (--on-*) yang sudah lolos kontras. Jangan bikin hex baru.
<body style="--accent: var(--orange); --on-accent: var(--on-orange)">
Tipografi
Display
Judul satu
Judul dua
Judul tiga
Kalimat pengantar yang agak besar, dipakai sekali di awal halaman.
Teks isi biasa. Lebarnya dibatasi .measure supaya nggak melebihi 68 karakter.
Teks kecil buat keterangan.
12.480 · angka selalu monospace tabular
<h1 class="h1">Judul</h1> <p class="lead measure">Pengantar.</p> <p class="small muted">Keterangan.</p> <span class="mono">12.480</span>
Tombol
<button class="btn btn-accent">Utama</button> <button class="btn btn-outline">Garis</button> <button class="btn btn-ghost">Polos</button> <button class="btn btn-accent btn-lg btn-block">Selebar induk</button>
Kartu & bidang
Dibatasi garis rambut, tanpa bayangan.
Naik sedikit waktu disentuh.
Latar abu, tanpa garis.
Bidang warna penuh
Satu penegas per halaman — ajakan, pengumuman, angka utama.
<div class="card">…</div> <a class="card card-link" href="#">…</a> <div class="card card-flat">…</div> <div class="slab">…</div>
Penanda & status
<span class="chip chip-solid">Terpilih</span> <span class="chip" style="color:var(--green)"><i class="dot" style="background:var(--green)"></i>Aktif</span> <span class="badge">Baru</span> <span class="avatar">HW</span> <span class="kbd">⌘</span>
Pemisah
kanan
<hr class="rule"> <div class="sep">atau</div>
Rangka muat (skeleton)
Bentuknya harus mengikuti isi yang bakal muncul — bukan kotak abu generik.
<div class="skeleton skeleton-circle" style="width:44px;height:44px"></div> <div class="skeleton skeleton-text" style="width:60%"></div>
Isian teks
<label class="field"> <span class="label">Nama proyek</span> <input class="input" placeholder="…"> <span class="hint">Keterangan singkat.</span> </label> <select class="select">…</select> <textarea class="textarea"></textarea>
Pilihan
<label class="choice"><input type="checkbox" class="check"> Label</label> <label class="choice"><input type="radio" name="g" class="radio"> Pilihan</label> <label class="choice"><input type="checkbox" class="switch"> Sakelar</label> <div class="toggles"> <button aria-pressed="true">Hari</button> <button aria-pressed="false">Minggu</button> </div>
Penggeser
Meter dipakai buat kekuatan sandi, level, atau tahapan.
<input type="range" class="slider" value="72"> <div class="meter"><i class="on"></i><i class="on"></i><i></i></div>
Isian gabungan
<div class="inputgroup"> <span class="affix">https://</span> <input class="input" value="hanif.app"> </div> <div class="otp"> <input inputmode="numeric"><input inputmode="numeric"><input inputmode="numeric"> </div>
Kalender
Buat isian tanggal sederhana, pakai <input type="date" class="input"> — pemilih bawaan browser sudah benar dan gratis.
<div class="calendar">
<div class="calendar-head">…</div>
<div class="calendar-grid">
<span class="dow">S</span>…
<span class="on">12</span><span class="in">13</span><span class="today">20</span>
</div>
</div>
Tabel
| Pelanggan | Paket | Status | Nilai | |
|---|---|---|---|---|
| Kirana Studio | Bisnis | Aktif | 12.400.000 | |
| Warung Sinar | Dasar | Aktif | 840.000 | |
| PT Marga Jaya | Bisnis | Tertunda | 9.100.000 | |
| Rumah Kopi | Dasar | Gagal | 420.000 |
<div class="toolbar">…</div> <div class="tablewrap"><table class="table"> <thead><tr><th>Nama</th><th class="num">Nilai</th></tr></thead> <tbody><tr><td>…</td><td class="num">12.400.000</td></tr></tbody> </table></div>
Angka
- Pendapatan
- 84,2jt
- Transaksi
- 1.284
- Pelanggan
- 312+12%
- Refund
- 7
<dl class="stat"> <dt>Pendapatan</dt> <dd>84,2<small>jt</small></dd> </dl>
Daftar
Hari ini · 10:24
Kemarin · 19:02
18 Agu · 08:41
17 Agu · 07:15
<div class="card card-pad-0"><div class="scroller"> <div class="row" style="padding:var(--s3) var(--s4)">…</div> <hr class="rule"> </div></div>
Korsel
Pakai scroll-snap bawaan, tanpa skrip.
Tiap kartu berhenti di tepi kiri.
Di HP jadi geser jari biasa.
<div class="carousel"> <div class="card">…</div> <div class="card">…</div> </div>
Media & rasio
16 : 9
4 : 3
1 : 1
<div class="ratio ratio-16-9"><img src="…" alt=""></div>
Navigasi sisi
<div class="split">
<nav class="side">
<a href="#" aria-current="true">Ringkasan</a>
<p class="group">Setelan</p>
<a href="#">Tim</a>
</nav>
<div class="stack">…</div>
</div>
Tab
Panel ringkasan.
Panel aktivitas.
Panel setelan.
<div class="tabs" data-tabs="x"> <button class="tab" aria-selected="true" data-panel="a">Ringkasan</button> <button class="tab" data-panel="b">Aktivitas</button> </div> <div data-panel-for="x" data-panel-name="a">…</div> <div data-panel-for="x" data-panel-name="b" hidden>…</div>
Jejak halaman
<nav class="crumbs"> <a href="/">Beranda</a><span class="sep">/</span> <span aria-current="page">Halaman ini</span> </nav>
Pindah halaman
<nav class="pager"> <button disabled>‹</button> <a href="#" aria-current="page">1</a> <a href="#">2</a> <button>›</button> </nav>
Menu tarik-turun
Pakai popover bawaan browser: buka-tutup, Esc, dan lapisan atasnya sudah ditangani sendiri.
<button class="btn btn-outline" popovertarget="m1">Tindakan ▾</button> <div popover id="m1" class="pop menu"> <button>Buka</button> <button>Duplikat<span class="shortcut">⌘D</span></button> <hr> <button class="danger">Hapus</button> </div> <div data-contextmenu="m2">Klik kanan di sini</div>
Dialog
<button class="btn btn-outline" data-open="dlg">Buka</button> <dialog class="dialog" id="dlg"> <div class="dialog-body">…</div> <div class="dialog-foot"><button class="btn btn-ghost btn-sm" data-close>Batal</button></div> </dialog>
Panel geser
<button class="btn btn-outline" data-open="sh">Buka</button> <dialog class="sheet" id="sh"> <!-- .sheet-bottom buat dari bawah --> <div class="sheet-body">…</div> </dialog>
Papan perintah
<dialog class="command" data-command>
<input placeholder="Ketik perintah…">
<div class="menu">
<p class="head">Navigasi</p>
<button>Buka dashboard</button>
</div>
</dialog>
Petunjuk singkat
Bikin app di *.hanif.app
<span class="tip"> <button class="btn btn-sm btn-outline">Tombol</button> <span class="tiptext">Penjelasan singkat</span> </span> <span class="hovercard"> <a href="#">@hanif</a> <span class="hovercard-panel">…</span> </span>
Lipatan
Apa bedanya tiga bidang halaman?
Boleh nambah warna baru?
Perlu framework?
<div class="accordion">
<details open>
<summary>Pertanyaan</summary>
<div class="body">Jawaban.</div>
</details>
</div>
Pesan
Muat ulang halaman buat pakai versi terbaru.
Semua perubahan sudah masuk.
Tersisa 12% dari jatah bulan ini.
Sambungan terputus. Coba lagi.
<div class="alert alert-ok"> <span class="alert-icon">✓</span> <div><strong>Tersimpan</strong><p>Keterangan.</p></div> </div>
Notifikasi lewat
Pesan lewat dipakai buat kabar yang nggak perlu dijawab. Kalau butuh keputusan, pakai dialog.
import { toast } from '/lib/ui.js'
toast('Tersimpan')
Kemajuan
<div class="progress"><i style="width:64%"></i></div>
Keadaan kosong
Bikin satu buat mulai — nggak sampai satu menit.
Keadaan kosong wajib punya satu tindakan jelas. "Nggak ada data" doang itu jalan buntu.
<div class="empty"> <strong>Belum ada proyek</strong> <p class="small muted">Bikin satu buat mulai.</p> <button class="btn btn-accent btn-sm">Bikin proyek</button> </div>