Lewati ke konten utama

Komponen

Design System · v1.18.0

Konsisten dari token sampai layar bisnis.

Freeday — sumber kebenaran token-driven & framework-agnostic. Warna, tipografi, spasi, dan 44 komponen aksesibel yang dirakit jadi layar nyata di Vue, React, atau Blazor. Nol dependency runtime, kontras WCAG AA di terang & gelap.

$ npm i @cahyo-dimas/freeday
44komponen
22enhancer · 0-dep
3adapter framework
AAkontras · terang & gelap

Integrasi framework

Adapter tipis — enhancer tetap sumber kebenaran, event fdy-* dijembatani ke reaktivitas framework. Vue, React, dan Blazor kini sama-sama punya komponen typed (10/10 parity): FdyCombo, FdyDatepicker, FdyCfl, FdyChart, FdyTable, FdyModal/FdyDrawer, dst. Tiap stack punya contoh layar faktur yang jalan (lihat examples/).

Baru mau pakai di project sendiri? Panduan langkah-demi-langkah per stack →

Playground

Pilih komponen, atur varian lewat kontrol Freeday (chip & switch), lihat pratinjau langsung, lalu salin markup-nya. Semua kelas berasal dari kit — nol dependency, siap tempel ke Vue / React / Blazor.

Komponen
HTML

Prinsip

Empat aturan yang menjaga sistem tetap konsisten seiring pertumbuhannya.

1 · Semantic saja

Komponen hanya menyentuh peran (Tier-2), tak pernah ramp mentah. Re-brand & tema cukup ubah token semantic.

2 · Grid 4px

Semua spasi kelipatan 4px lewat skala --space-*. Tak pernah nilai lepas.

3 · Satu aksen per layar

Satu aksi primer menonjol; sisanya ghost/secondary. Warna status ≠ warna aksen.

4 · Aksesibel sejak awal

Kontras WCAG AA di terang & gelap, fokus selalu terlihat, HTML native dulu sebelum ARIA.

Warna

Peran semantic (Tier-2). Komponen hanya menyentuh peran ini, tak pernah ramp mentah.

Tipografi

Display Sora · body IBM Plex Sans · data JetBrains Mono.

Faktur & laporan yang rapi

Teks isi memakai IBM Plex Sans — nyaman dibaca untuk paragraf, label, dan tabel data bisnis sehari-hari.

INV-1042 · Rp 1.240.000 · 2026-07-30

Spasi

Skala kelipatan 4px. Selalu var(--space-N), tak pernah nilai lepas.

--space-1 ·
--space-2 ·
--space-3 ·
--space-4 ·
--space-5 ·
--space-6 ·
--space-8 ·
--space-10 ·
--space-12 ·
--space-16 ·

Radius & Elevasi

Sudut & bayangan bertingkat — hierarki kedalaman yang konsisten.

Radius

xs ·
sm ·
md ·
lg ·
xl ·
full

Elevasi

shadow-1
shadow-2
shadow-3
shadow-4

Motion

Skala gerak terbatas & konsisten: tiga durasi (--dur-fast · --dur-base · --dur-slow ) dan dua easing yang keduanya decelerate (tanpa bounce/elastic). Gerak hanya untuk feedback, reveal, dan transisi state — bukan dekorasi. Semua otomatis nonaktif saat prefers-reduced-motion: reduce. Arahkan kursor ke track untuk merasakan easing-nya.

base · · ease-standard
slow · · ease-spring

Yang bergerak: Drawer & Modal beranimasi masuk dan keluar (slide / fade-scale + backdrop blur) lewat @starting-style + allow-discrete pada <dialog> native — buka lalu tutup, perhatikan animasi keluarnya. Overlay (menu, select, cascade, autocomplete, date/time picker) reveal saat dibuka; Accordion & Tabs me-reveal konten (fade + rise); baris tabel & kontrol punya transisi hover/press halus.

Tombol

Gradient gelap-ke-bawah + colored-glow. Satu aksi primer per layar; sisanya ghost.

Text + ikon · text-only (emphasis rendah) · icon-only (butuh aria-label).

Button group (segmented) & FAB (bulat · kecil · extended).

Menu & Split button

Popup aksi (pola menu-button WAI-ARIA APG) — keyboard //Home/End/Esc. Split button = aksi utama + toggle menu. Butuh freeday-menu.js.

Input

Inner-shadow + focus glow. Untuk error, pakai aria-invalid="true" — atribut ini melakukan dua hal sekaligus (state visual dan yang bisa dibaca screen reader), lalu aria-describedby menautkan pesan (help ber-id sama). .fdy-input--error hanya untuk kasus di mana state invalid bukan milik field itu sendiri.

Input group

Addon prefix/suffix bebas — teks (Rp / %), ikon dekoratif (__addon--icon), tombol aksi (__btn), atau tanpa addon sama sekali. Jadi "dengan ikon / tanpa ikon / ikon custom" cukup dari markup addon.

Rp
%

Choose-from-list

Field read-only yang di-backing master data (pelanggan, item, gudang…). Ikon kaca pembesar di kanan membuka dialog pencari; baris yang dipilih mengisi field (kode + nama sekaligus). Nilai selalu dipilih, tak pernah diketik. Butuh freeday-cfl.js.

Kode pelanggan
Nilai dipilih, bukan diketik.
Terisi otomatis dari baris terpilih.
Centang beberapa baris, lalu konfirmasi.

Pilih pelanggan

KodeNamaKotaSaldo
C-1001PT Sumber MakmurJakarta12.400.000
C-1002CV Berkah JayaBandung3.150.000
C-1003UD Cahaya AbadiSurabaya780.000
C-1004PT Mitra SentosaSemarang0
C-1005Toko Rejeki MakmurMedan5.600.000

Pilih item

PilihKodeNamaHarga
ITM-01Kertas A4 80gsm52.000
ITM-02Tinta Printer Hitam185.000
ITM-03Map Snelhecter3.500
ITM-04Pulpen Gel 0.512.000

Single-select commit saat klik baris (tanpa "OK"). Keyboard: ketik untuk mencari, masuk daftar, / navigasi, Enter pilih, Esc tutup. Fokus kembali ke tombol pemicu saat ditutup. Baris = server state: di app nyata, jadikan komponen terkontrol (callback fetchPage + cache), bukan store global.

Date picker

Trigger bergaya input + kalender popover — konsisten lintas-browser & bisa di-theme. (Native <input type="date"> tetap pilihan ringan bila tak butuh theming.) Rentang = dua picker tertaut; akhir tak boleh mendahului awal. Keyboard: / hari, / minggu, PgUp/PgDn bulan, Enter pilih, Esc tutup. Butuh freeday-datepicker.js.

Tanggal faktur
Periode laporan
Akhir tak boleh mendahului awal.

Varian ikon (konvensi kit): default (kalender), tanpa ikon lewat data-fdy-no-icon, atau ikon custom dengan <template data-fdy-icon> di dalam wrapper.

Default
Tanpa ikon
Ikon custom

Time picker

Trigger bergaya input + popup daftar waktu (pola listbox WAI-ARIA). Format 24 jam HH:MM; rentang & langkah diatur lewat data-min/data-max/data-step (default tiap 30 menit). Keyboard: buka, / pindah, Home/End, Enter pilih, Esc tutup. Butuh freeday-timepicker.js.

Jam mulai
Tiap 15 menit, 08:00–17:00

Varian ikon (konvensi kit): default (jam), tanpa ikon lewat data-fdy-no-icon, atau ikon custom dengan <template data-fdy-icon>.

Default
Tanpa ikon
Ikon custom

Datetime picker

Komposisi date picker + time picker jadi satu nilai — reuse dua komponen yang sudah ada, bukan popover monolitik. Composer freeday-datetime.js menyatukan keduanya dan memancarkan satu event fdy-datetime-change (value = YYYY-MM-DDTHH:MM). Varian ikon diwarisi dari tiap picker anak.

Jadwal kirim faktur
Tanpa ikon

File upload

Drop target yang juga membuka dialog berkas saat klik / Enter. State eksplisit — idle, drag-over, mengunggah (progress), selesai, error — karena "tidak terjadi apa-apa" adalah feedback unggah terburuk. Butuh freeday-upload.js. (Demo ini mensimulasikan progress; di app nyata, sambungkan event fdy-upload-add ke fungsi unggahmu.)

Seret berkas ke sini, atau klik untuk memilih PDF hingga 10 MB per berkas

Dua state terminal (statis) — terunggah & ditolak:

PO-48213-acme.pdf
248 KB · Terunggah
scan-copy.png
Bukan PDF — hanya berkas PDF yang diterima.

Stepper / Wizard

Alur multi-langkah — indikator progres (nomor → centang), panel per langkah, tombol Kembali/Lanjut. Langkah yang sudah dilewati bisa diklik untuk ditinjau (linear, tak bisa lompat maju). Butuh freeday-stepper.js.

Slider

Native <input type="range"> di-tema lewat accent-color — keyboard & ARIA bawaan, fill & thumb otomatis. freeday-slider.js cuma menyalin nilai ke <output>. Warna: primary/accent/danger.

Diskon 15
0%100%
Anggaran 30
Rp 0Rp 100 jt

Rating

Bintang — grup radio native (panah kiri/kanan untuk memilih, ter-asosiasi form). Terisi vs kosong dibedakan isi vs garis (bukan warna saja). Ada varian read-only. Butuh freeday-rating.js.

Autocomplete

Combobox editable — ketik untuk memfilter saran (pola APG combobox + listbox), keyboard //Enter/Esc. Butuh freeday-autocomplete.js. (Opsi statis di-filter di klien; di app nyata, fetch/filter server-side.)

Ketik untuk menyaring; pilih dengan panah + Enter.

Cascade select

Pemilih hierarki (drill-down) — model data = <ul> bersarang tersembunyi: <li> dengan anak <ul> adalah cabang, tanpa anak adalah daun. Cabang membuka level berikut, daun memilih (nilai = jalur lengkap). Keyboard: / pindah, /Enter masuk cabang / pilih daun, /Backspace naik level, Esc tutup. Butuh freeday-cascade.js.

  • Elektronik
    • Handphone
      • Android
      • iOS
    • Laptop
    • Televisi
  • Fashion
    • Pria
    • Wanita
    • Anak
  • Lainnya

Password & mask

Field kata sandi dengan tombol tampil/sembunyi (data-fdy-password — memakai kembali chrome tombol input-group) dan input ber-format saat mengetik (data-fdy-mask: # digit, A huruf, * alnum; karakter lain jadi literal otomatis). Butuh freeday-mask.js.

Form validation

Validasi native (Constraint Validation API) di-wire ke error inline aksesibel — aria-invalid + pesan ter-aria-describedby, fokus ke field invalid pertama saat submit, lalu re-validasi live tiap blur/input. Pesan custom via data-fdy-msg-*, cocokkan antar-field via data-fdy-match. Coba tekan Simpan saat kosong. Butuh freeday-form.js.

Validasi inline

Header + detail (dokumen) — .fdy-form-grid + tabel

Rincian item
ItemQtyHargaJumlah
Kertas A4 80gsm1050.000500.000
Tinta Printer Hitam2120.000240.000
TotalRp 740.000

Filter bar

Baris filter yang konsisten — .fdy-filterbar membungkus beberapa .fdy-field. Tiap field ikut ritme lebar (--w-sm · default · --w-lg · --w-xl); satu field --w-grow (biasanya pencarian) menyerap sisa ruang; aksi (__actions) menempel di ujung, sejajar kontrol. Membungkus rapi di layar sempit. Nol JS — cukup layout di atas .fdy-field.

Cari
Status
Kategori

Select (combobox)

Dropdown berdesain penuh (pola WAI-ARIA APG) — popup bisa distyle, keyboard ↑↓/Enter/Esc/ketik. Butuh freeday-select.js. Varian ikon: caret default, tanpa lewat fdy-combo--no-icon, atau custom (--no-icon + .fdy-combo__icon di dalam tombol).

Status faktur (default)
Tanpa ikon
Ikon custom

Checkbox · Radio · Switch

Native <input> distyle — Space, asosiasi label, :focus-visible tetap native.

Alert

Pesan inline. Varian danger memakai role="alert".

InfoSinkronisasi terakhir 5 menit lalu.
BerhasilFaktur INV-1042 disimpan.
PerhatianStok barang menipis di 3 gudang.

Toast

Notifikasi sekilas di live-region. Panggil Freeday.toast({variant,title,message})mengembalikan elemen toast. Beri key agar toast dengan key sama menggantikan yang lama (bukan menumpuk saat error yang sama meletup beruntun); tutup lebih awal dengan Freeday.dismiss(node|key).

Tooltip

Muncul saat hover/focus. Asosiasi via aria-describedby.

Ekspor ke Excel (.xlsx)

Tabs

Pola APG — panah ←/→, Home/End, roving tabindex. Butuh freeday-tabs.js.

Total tagihan Rp 1.240.000, jatuh tempo 30 Juli 2026.

Breadcrumb

Pagination

Table

Tabel semantik statis — <caption>, <th scope>, angka tabular kanan.

Faktur terbaru
FakturPelangganStatusNilai
INV-1042PT Sumber MakmurLunas1.240.000
INV-1043CV Berkah JayaTertunda290.000
INV-1044Toko AmanahDraft0

Data table

Interaktif: cari global, urutkan (klik judul kolom), filter per kolom (ikon corong — teks berisi, enum checklist, angka rentang), pilih baris → bar aksi massal, paginasi. Butuh freeday-table.js.

Daftar faktur (interaktif)
INV-1042PT Sumber MakmurLunas1.240.000
INV-1043CV Berkah JayaTertunda290.000
INV-1044Toko AmanahDraft0
INV-1045UD Maju TerusLunas4.750.000
INV-1046PT Cahaya AbadiTertunda820.000
INV-1047Koperasi SejahteraBatal150.000
INV-1048PT Sumber MakmurLunas3.120.000
INV-1049Toko AmanahDraft67.000
INV-1050CV Berkah JayaLunas1.990.000
INV-1051PT Cahaya AbadiTertunda540.000

States

Placeholder kosong / error untuk area data.

Belum ada faktur
Faktur yang kamu buat akan muncul di sini.
Gagal memuat
Tidak bisa mengambil data dari server.

Charts

Sparkline, bar, line, area, dan donut — SVG/CSS murni, tanpa dependency. Seri tunggal via data-values; multi-seri via data-series (JSON). Cartesian (line/area/bar) menggambar sumbu ber-tema (--chart-grid/--chart-tick), legenda otomatis untuk ≥2 seri, dan format nilai data-fdy-format="number|percent|currency". Warna dari token → chart ikut re-warna saat data-theme berubah. Multi-seri memakai palet kategorikal tervalidasi --chart-1--chart-8 (urutan tetap); override lewat data-fdy-colors — nama token semantik (primary…) atau slot chart-1chart-8 untuk mengunci warna per kategori. Untuk data reaktif: panggil FreedayChart.update(el) atau pakai <FdyChart> dari @cahyo-dimas/freeday/vue. Butuh freeday-chart.js; tiap chart role="img" + aria-label + fallback tabel di dalam elemen.

Pendapatan

6 bulan terakhir

Rp 18 jt

Faktur / hari

Status faktur

Posting vs draft

Line multi-seri · sumbu persen

Posting vs draft (%)
BulanPostedDraft
Jun8816

Nilai faktur

Area · sumbu USD

Nilai faktur (USD)
HariNilai
Jum7200

Faktur per kanal

Bar bertumpuk (stacked)

Faktur per kanal
KuartalOnlineCabangMitra
Q4521914

Tree view

Hierarki lewat <details> native — buka/tutup dengan klik atau Enter/Space, tanpa JS. Cabang bisa dilipat; daun = baris biasa. Varian checkbox (kanan) menambah pilihan bertingkat: centang cabang → semua anak ikut; sebagian anak → cabang jadi indeterminate. Butuh freeday-tree.js untuk cascade; centang tak pernah membuka/menutup cabang.

Dasar (tanpa JS)

  • Pelanggan
    • Jakarta
      • PT Sumber Makmur
      • PT Cahaya Abadi
    • Bandung
      • CV Berkah Jaya
  • Item
    • Kertas A4 80gsm
    • Tinta Printer Hitam

Dengan checkbox (cascading)

  • Pelanggan
    • Jakarta
      • PT Sumber Makmur
      • PT Cahaya Abadi
    • Bandung
      • CV Berkah Jaya
  • Item
    • Kertas A4 80gsm
    • Tinta Printer Hitam

Card

--interactive = kursor + hover-lift untuk kartu yang diberi handler klik. Kalau kartunya adalah kontrol (baris pemilih yang keyboard-reachable & diumumkan), render sebagai <button> dan tambah --button — reset kotak tombol UA tanpa membuang surface/border kartu.

Faktur INV-1042

Jatuh tempo 30 Juli 2026. Total tagihan Rp 1.240.000.

Interactive

Arahkan kursor — kartu terangkat (hover-lift).

Badge

Inline untuk status; overlay untuk angka/dot yang menempel di sudut ikon, tombol, atau teks.

Baru Lunas Tertunda Batal Draft Arsip

Badge notifikasi = overlay. Bukan komponen terpisah dari “surat”: angka/“99+”/ikon/titik yang menempel di sudut elemen apa pun — lonceng, amplop, avatar, atau tombol. Bungkus konten dengan .fdy-badge-wrap, tambahkan .fdy-badge-ov. Warna ber-teks AA (default gelap · primary · danger); titik untuk accent/info/success/warning.

Bug Reports

Avatar

Ukuran --sm / default / --lg, plus grup bertumpuk. Untuk membedakan avatar berinisial sama (mis. banyak nama "PT …"), pakai --tone-1--tone-8 — tint dekoratif yang tetap kontras AA di terang & gelap; hash indeks stabil dari nama lengkap (bukan dari inisial).

SM BJ TA SM BJ TA
PT PT PT PT PT PT PT PT

Chip

Tiga peran: default / hapus (tag statis atau filter aktif yang bisa dihapus), choice (toggle pilih), dan filter (toggle dengan centang). Yang interaktif = <button aria-pressed> dikelola freeday-chip.js — bungkus dalam data-fdy-chips, tambah data-single untuk pilih-satu.

Semua Status: Lunas Bulan: Juli

Detail (key-value)

Tampilan ringkas untuk halaman detail faktur / pelanggan.

Faktur INV-1042

Pelanggan
PT Sumber Makmur
Status
Lunas
Jatuh tempo
30 Juli 2026
Total
Rp 1.240.000

Progress & Spinner

Skeleton

--title/--text untuk teks, --circle untuk bentuk bulat, dan --avatar (+--avatar-sm/--avatar-lg) yang seukuran .fdy-avatar — jadi placeholder memesan kotak yang persis sama dan tak ada geser tata letak saat data datang.

Timeline

Feed peristiwa vertikal — titik penanda pada garis penghubung, dengan waktu & deskripsi. Warna titik menandai status (didampingi teks, bukan warna saja). Pure CSS.

  1. 21 Jul 2026 · 09:12

    Faktur dibuat

    INV-1042 untuk PT Sumber Makmur, Rp 1.240.000.

  2. 21 Jul 2026 · 09:15

    Dikirim ke pelanggan

    Email terkirim ke finance@sumbermakmur.co.id.

  3. 25 Jul 2026 · 14:30

    Jatuh tempo mendekat

    Sisa 5 hari sebelum jatuh tempo.

  4. 28 Jul 2026 · 10:02

    Lunas

    Pembayaran diterima via transfer bank.

App bar

Bar atas standalone — brand · aksi · spacer. Bisa sticky, elevated, dense, atau berwarna. Tombol hamburger biasanya membuka drawer (menu samping).

Freeday
CD

Berwarna (primary) & dense — kontrol jadi on-color.

Faktur

Product appbar — komposisi kaya di dalam .fdy-app__topbar (App shell), beda dari .fdy-appbar berdiri sendiri di atas. Urutan: nav toggle → .fdy-breadcrumb → judul halaman (.fdy-app__title, auto-spacer kanan) → pencarian (.fdy-input-group + __addon--icon) → menu pengguna (.fdy-menu). Salin blok ini langsung ke dalam <header class="fdy-app__topbar"> shell Anda.

INV-1042

Vue/React: useFreeday menghidrasi .fdy-menu otomatis lewat enhancer data-fdy-menu (mekanisme sama dengan freeday-menu.js vanilla) — cukup pasang markup di atas di dalam komponen, tak perlu wiring buka/tutup manual.

Sidebar menu

Menu navigasi vertikal dari .fdy-nav (dipakai App shell & sidebar dokumentasi ini). Tiap node bebas: ikon + teks, teks saja, atau tambah badge angka. .fdy-nav__group = seksi collapsible; .fdy-nav__tree = item bersarang — dua-duanya native <details> (zero-JS, keyboard bawaan). Di App shell, sidebar jadi off-canvas drawer di mobile.

Drawer

Panel samping temporary (overlay + backdrop) di atas <dialog> native — focus-trap, Esc, dan kembalikan-fokus gratis. Kiri atau kanan. Slide masuk & keluar dengan backdrop yang mem-blur — tutup lewat Esc/backdrop untuk melihat animasi keluarnya. Butuh freeday-drawer.js. (Tombol hamburger di App bar di atas juga membukanya.)

Menu
Filter
Status

Accordion

Native <details> — zero-JS, aksesibel bawaan. Panel me-reveal (fade + rise) saat dibuka; chevron ikut berputar.

Info pengiriman
Dikirim via JNE, estimasi 2–3 hari kerja.
Metode pembayaran
Transfer bank, virtual account, atau kartu kredit.
Kebijakan retur
Retur diterima maksimal 7 hari setelah barang sampai.

Divider · Kbd

Bagian atas


Bagian bawah

Simpan cepat dengan Ctrl + S, tutup dialog dengan Esc.

Modal

Native <dialog> — focus-trap, Esc, backdrop gratis dari browser. Muncul & menghilang dengan fade + skala halus (backdrop ikut mem-blur), simetris masuk-keluar.

Hapus faktur?

Faktur INV-1042 akan dihapus permanen. Tindakan ini tidak bisa dibatalkan.

Contoh: satu layar bisnis

Semua komponen dirakit jadi layar faktur nyata.

Lewati ke konten utama

Faktur

Daftar faktur
FakturPelangganStatusNilai
INV-1042PT Sumber MakmurLunas1.240.000
INV-1043CV Berkah JayaTertunda290.000

Faktur baru

Status

Breakpoint

Utilitas tampilan responsif + provider JS. Skala (min-width): sm 600 · md 960 · lg 1280 · xl 1920. Kelas .fdy-hide-below-* / .fdy-hide-above-* menyembunyikan per rentang. freeday-breakpoint.js menstempel <html data-breakpoint> + memancarkan fdy-breakpoint-change. Ubah ukuran jendela untuk melihatnya.

Breakpoint saat ini:

Terlihat di md ke atas (≥ 960px) — konten desktop
Terlihat di bawah md (< 960px) — konten mobile

Aksesibilitas

Kontrak yang dipegang setiap komponen — bukan renungan belakangan.

  • Kontras teks & kontrol lolos WCAG AA di tema terang & gelap.
  • :focus-visible selalu terlihat — outline/ring 2–3px.
  • Status tak hanya lewat warna (ikon/teks pendamping).
  • HTML native dulu; ARIA hanya saat native tak cukup.
  • Komponen interaktif ikut pola WAI-ARIA APG (role/aria/keyboard).
  • Modal & dialog: focus-trap, Esc, fokus kembali ke pemicu.
  • Input error: aria-invalid + aria-describedby.
  • Menghormati prefers-reduced-motion.
  • Target sentuh memadai; label jelas pada tiap kontrol.