Keranjang Jastip · Sesi 1

Styleguide

Seluruh token dari DESIGN.md, dirender langsung dari tema Tailwind. Kalau ada yang tidak cocok dengan DESIGN.md, DESIGN.md yang benar dan tema yang harus diperbaiki.

Warna

Penamaan mengikuti Material Design 3. Pola on-X berarti warna konten di atas permukaan X — kalau memakai bg-primary, teksnya wajib text-on-primary. Jangan mengarang pasangan sendiri.

Primary

Aksi utama, state navigasi aktif, isi chart, momen brand. Kontras primary 6,7:1 di atas putih — aman jadi warna teks termasuk teks kecil.

#5f3add

primary

#ffffff

on-primary

#7857f8

primary-container

#fffbff

on-primary-container

#e6deff

primary-fixed

#cabeff

primary-fixed-dim

#1c0062

on-primary-fixed

#4918c8

on-primary-fixed-variant

#cabeff

inverse-primary

#613de0

surface-tint

Secondary & Tertiary

Peran pendukung. Netral, tidak bersaing dengan primary.

#5e5e5e

secondary

#ffffff

on-secondary

#e2e2e2

secondary-container

#646464

on-secondary-container

#5a5c5f

tertiary

#ffffff

on-tertiary

#737477

tertiary-container

#fcfcff

on-tertiary-container

Surface & Background

Tangga permukaan. lowest untuk kartu data, low untuk area yang sedikit tenggelam seperti isi input dan baris tabel bergaris.

#f9f9ff

background

#151c27

on-background

#f9f9ff

surface

#d3daea

surface-dim

#f9f9ff

surface-bright

#ffffff

surface-container-lowest

#f0f3ff

surface-container-low

#e7eefe

surface-container

#e2e8f8

surface-container-high

#dce2f3

surface-container-highest

#dce2f3

surface-variant

#151c27

on-surface

Teks utama + isian tombol gelap

#484555

on-surface-variant

Teks sekunder · 8,85:1 AAA

#2a313d

inverse-surface

#ebf1ff

inverse-on-surface

Outline

Garis pembatas 1px. Ini pengganti bayangan, bukan pelengkap.

#797587

outline

4,29:1 — GARIS SAJA, jangan untuk teks

#c9c4d8

outline-variant

Border standar 1px

Semantik

success untuk lunas dan tren naik, warning untuk menunggu dan tenggat, error untuk gagal dan tren turun. Tidak ada warna aksen lain di luar ini.

#15803d

success

#ffffff

on-success

#d7f4e3

success-container

#04552a

on-success-container

#b45309

warning

#ffffff

on-warning

#fdeacd

warning-container

#6b3103

on-warning-container

#ba1a1a

error

#ffffff

on-error

#ffdad6

error-container

#93000a

on-error-container

Dua aturan yang paling sering dilanggar

  • outline #797587 kontrasnya 4,29:1 — cukup untuk garis, gagal untuk teks. Jangan pernah dipakai sebagai warna tulisan.
  • Jangan pakai kelas warna Tailwind mentah (green-500, amber-400, emerald-*). Semua warna lewat token. Kode referensi melanggar ini 76×; semuanya diperbaiki saat dibangun.

Tipografi

Pakai utility type-* saat membangun halaman — itu menyetel ukuran, typeface, dan tabular figures sekaligus. Utility text-* bawaan hanya menyetel ukuran. type-label-caps sengaja tidak memaksa huruf besar: kode kartu sv3-125 harus tampil apa adanya. Untuk header kolom tabel, tambahkan kelas uppercase sendiri.

type-display-lg

Plus Jakarta Sans

32px / 40px · 700 · -0.02em · mobile 24px

Profit Bersih Bulan Ini

type-headline-md

Plus Jakarta Sans

24px / 32px · 600 · -0.01em · mobile 20px

Order Terbaru

type-title-sm

Plus Jakarta Sans

16px / 24px · 600

Charizard ex — Obsidian Flames

type-body-md

Inter

14px / 20px · 400

Badan antarmuka. Ini level yang paling banyak dipakai di seluruh sistem.

type-body-sm

Inter

12px / 18px · 400

Caption, teks bantuan di bawah field, dan metadata sekunder.

type-data-tabular

Inter

14px / 20px · 600 · tabular-nums

Rp 947.500.000 · Rp 111.111.111

type-metric-lg

Inter

30px / 36px · 700 · -0.02em · tabular-nums

Rp 947.500.000

type-label-caps

JetBrains Mono

11px / 16px · 500 · 0.05em

sv3-125 · KJ-1521 · 0O1l

Uji tabular figures: dua baris di bawah harus punya lebar yang sama persis. Kalau goyang, tabular-nums tidak aktif.

Rp 111.111.111

Rp 947.500.000

Radius

Jenjangnya bermakna: makin besar dan makin permanen sebuah elemen, makin besar radiusnya. Jangan menyeragamkan semuanya ke satu nilai.

rounded-sm

0.25rem · 4px

Checkbox, tag kecil

rounded

0.5rem · 8px

Tombol, input, dropdown

rounded-md

0.75rem · 12px

Kartu, panel, modal

rounded-lg

1rem · 16px

Panel besar

rounded-xl

1.5rem · 24px

Kontainer terluar

rounded-full

9999px

Badge, chip status, avatar

Spacing

Semuanya kelipatan baseline 4px. Kerapatan sengaja tinggi — ini antarmuka padat data, dan whitespace berlebih memaksa scroll yang menyembunyikan angka.

xs

4px

Jarak terkecil, di dalam chip

sm

8px

Antar field yang berhubungan

md

16px

Padding standar dalam kartu

gutter

20px

Gutter grid

lg

24px

Antar section

xl

32px

Pemisah blok besar

container-max

1440px

Lebar maksimum area konten — dipakai halaman ini.

sidebar-width

240px

Sidebar kiri tetap di shell admin.

Elevation

Datar dengan garis rambut. Kedalaman datang dari warna dan border 1px outline-variant, bukan dari bayangan. Arahkan kursor ke kartu kedua untuk melihat satu-satunya bayangan yang diizinkan.

Level 0

Latar

background #f9f9ff

Level 1

Permukaan + hover

surface-container-lowest, border 1px

Kartu kontras

Rp 947.500.000

Maksimal satu per layar. Tanpa bayangan sama sekali.

Chip status

Pemetaan ini tetap. Tidak ada status kelima tanpa menambahkannya ke tabel di DESIGN.md terlebih dulu.

LunasDPBelum BayarBatalGagal

Yang ditampilkan di sini token warnanya saja. Komponen StatusChip yang memakainya ada di bagian Komponen di bawah.


Bagian dua

Komponen

Semuanya ada di src/components/ui. Halaman berikutnya memakai komponen dari sini — jangan menyalin markup berulang antar halaman.

Button

Aksi utama memakai isian on-surface gelap dengan teks putih — bobot gelap ala Ramp. Aksi sekunder memakai surface-container-lowest dengan border 1px. Aksi ketiga tanpa isian dan tanpa border. Semua tombol rounded 8px dan tinggi minimal 44px.

primary

secondary

ghost

size sm

block

State hover dan focus tidak bisa dibekukan di halaman ini — arahkan kursor ke tombol di atas, lalu tekan Tab untuk melihat cincin fokus. Cincin fokus wajib terlihat; kalau tidak muncul, itu bug.

Input

Border 1px outline-variant, padding 8px, body-md. Saat fokus, border berubah ke primary dengan cincin luar 2px primary beropasitas 10%.

⌘K

Kode ditarik dari Pokémon TCG API.

Nomor harus diawali 628, bukan 08.

Ketik angkanya saja; titik pemisah muncul sendiri. Coba sisipkan digit di tengah — kursor tidak melompat.

Card & ContrastCard

Kartu memakai surface-container-lowest dengan border 1px outline-variant, radius 12px, padding 16px.

Kartu biasa

Level 1 — permukaan dengan garis rambut.

Kedalaman datang dari warna dan border, bukan bayangan.

Kartu interactive

Arahkan kursor ke sini.

Border sedikit menggelap plus bayangan ambient sangat tipis. Ini satu-satunya bayangan yang diizinkan.

ContrastCard sengaja tidak dirender lagi di sini

Maksimal satu kartu kontras gelap per layar. Contoh hidupnya ada di Elevation dan pemakaian sungguhannya — kartu Profit Bersih — ada di KpiCard. Menambahkan satu lagi di sini justru akan melanggar aturan yang sedang didokumentasikan.

StatusChip & Badge

StatusChip terkunci ke lima status di tabel DESIGN.md — menambah status keenam akan gagal saat compile, bukan diam-diam lolos dengan warna karangan. Label lain memakai Badge.

StatusChip

LunasDPBelum BayarBatalGagal

Badge caps

Pre-OrderReadyTersediaHabis

Badge biasa

NMJPMenunggu Verifikasi

DeltaBadge

+12%+23%-5%

Kenapa DeltaBadge punya prop `good` terpisah

Arah baik/buruk bergantung metrik, bukan tanda angka. Kenaikan “Order Belum Lunas” itu buruk dan harus merah meski angkanya naik. Logika ini ada di data, bukan di komponen.

KpiCard

Struktur tetap: label → angka → badge delta → sparkline → tautan detail, dengan ikon persegi membulat di kanan atas. Urutan ini tidak boleh diubah antar halaman.

Omset Bulan Ini

Rp 947.500.000

Profit Bersih

Rp 189.400.000

Order Belum Lunas

34

Rp 42.300.000

Kartu Terjual

1.248

DataTable

Tanpa garis vertikal, hanya garis horizontal. Header label-caps, kolom nominal rata kanan dengan tabular figures, baris punya state hover. Perkecil jendela sampai di bawah 768px — tabel ini berubah jadi daftar kartu, bukan tabel yang digeser ke samping.

ProductCard

Kartu produk untuk katalog publik. Badge tipe READY / PRE-ORDER wajib ada — kartu yang sama boleh muncul di kedua halaman dengan harga berbeda, dan badge inilah yang mencegah buyer bingung. Harga selalu rupiah penuh, tanpa singkatan.

  • Tanpa gambar
    Ready

    Pokémon · sv3-125

    Charizard ex

    Obsidian Flames

    JPA

    Rp 4.850.000

  • Tanpa gambar
    Pre-Order

    One Piece · op01-120

    Monkey D. Luffy

    Romance Dawn

    JPA

    Rp 6.200.000

  • Tanpa gambar
    ReadySisa 1

    Pokémon · s6a-095

    Umbreon VMAX (Alt Art)

    Eevee Heroes

    JPAPSA 10

    Rp 18.500.000

  • Tanpa gambar
    ReadyHabis

    Pokémon · sv2a-205

    Mew ex SAR

    151

    ENB

    Rp 2.100.000

Dari kiri: stok normal, pre-order, sisa 1 dengan grading, dan habis (diredupkan). Gambar sengaja dikosongkan di sini supaya yang terlihat strukturnya, bukan fotonya.

Sidebar & TopBar

Shell layout: sidebar kiri tetap 240px + top bar + area konten. Di bawah 768px sidebar jadi hamburger — tombolnya muncul di kiri judul, coba perkecil jendela lalu tekan tombolnya.

Dashboard

Batch Osaka · Juli 2026

Area konten. Grid 12 kolom, lebar maksimum 1440px.

Tombol “Input Rekap” di sini gelap, bukan ungu. dashboard-desktop.png dan tambah-listing-desktop.png menampilkannya berbeda; DESIGN.md menang — aksi utama memakai isian on-surface.

Skeleton, Empty & Error

Setiap tampilan yang mengambil data wajib punya tiga state ini. Skeleton, bukan spinner — skeleton menunjukkan bentuk yang akan datang, jadi layar tidak melompat saat data masuk.

Skeleton KPI

Skeleton tabel

Empty state

Belum ada rekap belanja

Dashboard baru bisa menghitung profit setelah trip pertama direkap.

Mengarahkan ke aksi berikutnya, bukan sekadar bertuliskan “Tidak ada data”.

Error state

Gagal memuat data

Periksa koneksi lalu coba lagi. Kalau terus berulang, kabari admin.

Skeleton dasar