h hanif ui 35 bagian llms.txt

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.

tokens.csslib/ui.csslib/layout.csslib/ui.js — opsional
<link rel="stylesheet" href="/lib/ui.css">
<link rel="stylesheet" href="/lib/layout.css">
<script src="/lib/ui.js" type="module"></script>

Tiga aturan

01

Netral dulu

Bidang dan garis pakai hitam-putih. Warna baru muncul waktu ada yang perlu ditekan atau ditandai.

02

Satu warna penuh per layar

Kalau ada dua bidang warna besar, salah satunya pasti nggak penting.

03

Bentuk dulu, baru warna

Tentukan bidang halaman sebelum menyentuh palet.

Bidang halaman

Tiga watak. Pilih satu di awal, jangan dicampur dalam satu halaman.

KelasLebarBuat apa
.shell-wide1760Etalase, galeri, landing — kesan layar lega
.shell-dash1560Dashboard: lebar, padat data, hiasan minim
.shell-compact460App 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

Biru

Tindakan utama, tautan, fokus

--blue #0040ff
Oranye

Perlu perhatian, tertunda

--orange #ff5c00
Hijau

Berhasil, aktif, naik

--green #00a63e
Merah

Gagal, hapus, turun

--red #ff2d2d
Kuning

Peringatan, sorotan

--yellow #ffc400
Ungu

Fitur baru, label khusus

--purple #6d28ff

Tiap 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

Kartu biasa

Dibatasi garis rambut, tanpa bayangan.

Bisa diklik

Naik sedikit waktu disentuh.

Rata

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

TerpilihNetralGarisAktifTertundaGagalBaru
HWRABS+4
K
<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


atau
Bagian kiri
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

https:///blog
<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

Agustus 2026
SSRKJSM 28293031123 45678910 11121314151617 18192021222324 25262728293031

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

Status: semua 4 baris
PelangganPaketStatusNilai
Kirana StudioBisnisAktif12.400.000
Warung SinarDasarAktif840.000
PT Marga JayaBisnisTertunda9.100.000
Rumah KopiDasarGagal420.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

Terima dari Rani

Hari ini · 10:24

+250.000

Bayar listrik

Kemarin · 19:02

−318.000

Transfer ke Budi

18 Agu · 08:41

−1.200.000

Kopi Tuku

17 Agu · 07:15

−28.000
<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

<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.

<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

1–10 dari 84
<nav class="pager">
  <button disabled>‹</button>
  <a href="#" aria-current="page">1</a>
  <a href="#">2</a>
  <button>›</button>
</nav>

Dialog

Ganti nama proyek

Hapus proyek?

Tindakan ini nggak bisa dibatalkan.

<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

Setelan

Bagikan

<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

atau tekan K
<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

Muncul di atas, hilang sendiri @hanif
HW
Hanif

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?
Lebar buat etalase, dashboard buat data, ringkas buat app kecil. Pilih satu, jangan dicampur.
Boleh nambah warna baru?
Nggak. Enam warna yang ada sudah punya pasangan teks yang lolos kontras. Kalau butuh warna lain, tawarkan dulu.
Perlu framework?
Nggak. Semuanya HTML biasa plus dua berkas CSS. JavaScript-nya opsional, cuma buat tab, papan perintah, dan menu klik kanan.
<div class="accordion">
  <details open>
    <summary>Pertanyaan</summary>
    <div class="body">Jawaban.</div>
  </details>
</div>

Pesan

i
Versi baru tersedia

Muat ulang halaman buat pakai versi terbaru.

Tersimpan

Semua perubahan sudah masuk.

!
Kuota hampir habis

Tersisa 12% dari jatah bulan ini.

Gagal menyimpan

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

memuat…
<div class="progress"><i style="width:64%"></i></div>

Keadaan kosong

🗂
Belum ada proyek

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>