--- title: RTG Design System v1 app: Raja Topup Games status: locked version: 1.0.0 locked_date: 2026-11-15 prd_ref: "[[RTG-DOKUMENTASI]]#PRD v1 β Raja Topup Games" standard_ref: "[[PRD_STANDARD]]#7.2 Design System (WAJIB sebelum coding UI)" preview: "[[design-system-preview]]" --- # RTG Design System v1.0.0 β LOCKED > **Status:** π Locked 2026-11-15 Β· Sumber: PRD v1 Β§7.1 + DISKUSI-02 Β§13 > **Aturan:** Implementasi TIDAK BOLEH melenceng dari token ini. Perubahan token = versi baru + update `RTG-DOKUMENTASI.md`. --- ## 1. Token Warna ### 1.1 Inti (dari PRD Β§7.1 β TIDAK diubah) | Token | Hex | Pemakaian | |---|---|---| | `--ink` | `#0F172A` | Teks utama, heading | | `--ink-2` | `#64748B` | Teks sekunder, muted, caption | | `--brand` | `#1E3A8A` | Brand navy, header, link | | `--brand-strong` | `#1D4ED8` | Hover/focus brand, CTA | | `--info` | `#0284C7` | Aksen informasi, **hanya non-teks** (lihat Β§1.3) | | `--success` | `#059669` | Indikator sukses, **hanya non-teks** (lihat Β§1.3) | | `--warning` | `#D97706` | Indikator warning, **hanya non-teks** (lihat Β§1.3) | | `--danger` | `#DC2626` | Indikator error, **hanya non-teks** (lihat Β§1.3) | | `--surface` | `#FFFFFF` | Background kartu/input | | `--surface-2` | `#F8FAFC` | Background section, zebra table | | `--line` | `#E2E8F0` | Border | | `--accent` | `#F59E0B` | Amber β flash sale, diskon, highlight | ### 1.2 Pairing teksβbackground (WAJIB, hasil hitung script) Semua rasio di bawah **dihitung oleh script** (`contrast_check.py`), bukan perkiraan. Sumber: `assets/contrast-report.txt`. | Pasangan | Rasio | Status | |---|---:|---| | `--ink` di `--surface` | 17.85:1 | β AAA | | `--ink` di `--surface-2` | 16.68:1 | β AAA | | `--ink-2` di `--surface` | 4.76:1 | β AA | | `--ink-2` di `--surface-2` | 4.45:1 | β οΈ hanya untuk teks β₯16px bold / β₯18px (large text) | | `--brand` di `--surface` | 11.29:1 | β AAA | | `--brand-strong` di `--surface` | 8.10:1 | β AAA | | `--brand` di `--surface-2` | 10.57:1 | β AAA | | `--brand` di tint brand `#EFF6FF` | 10.67:1 | β AAA | | putih di `--brand` (tombol solid) | 11.29:1 | β AAA | | putih di `--brand-strong` (tombol solid) | 8.10:1 | β AAA | | `--ink` di `--accent` (badge diskon) | 8.31:1 | β AAA | > **Rule:** `--ink-2` **DILARANG** untuk body text di atas `--surface-2`. Di background terang (kebanyakan), 4.76:1 aman. ### 1.3 Token status β pasangan badge DERIVED **Temuan audit (EN-008):** 4 dari 6 token status di PRD Β§7.1 **GAGAL** sebagai warna teks: | Token PRD | Rasio di putih | Status | |---|---:|---| | `--success` `#059669` | 3.77:1 | β FAIL | | `--warning` `#D97706` | 3.19:1 | β FAIL | | `--danger` `#DC2626` | 4.54:1 | β οΈ borderline | | `--info` `#0284C7` | 4.10:1 | β FAIL | **Solusi:** token PRD tetap dipakai sebagai **indikator non-teks** (icon, border, dot, progress bar, chart). Untuk **badge dengan teks**, dipakai pasangan dark-ink + tint berikut β semuanya **β₯ 4.5:1** di atas putih DAN di atas tint-nya: | Badge | Ink | Tint | Rasio |-state | |---|---|---|---:|---| | Sukses | `#047857` | `#ECFDF5` | 5.02:1 | β | | Peringatan | `#92400E` | `#FFFBEB` | 8.29:1 | β | | Bahaya | `#B91C1C` | `#FEF2F2` | 6.30:1 | β | | Info | `#075985` | `#F0F9FF` | 8.64:1 | β | | Netral | `#334155` | `#F1F5F9` | 8.62:1 | β | | Menunggu | `#075985` | `#F0F9FF` | 8.64:1 | β | Token derived ini **tidak mengubah** token PRD β ini pasangan terpisah, dicatat sebagai temuan audit di `RTG-DOKUMENTASI.md` (EN-008). ### 1.4 Token turunan ```css --ring: 0 0 0 3px rgb(29 78 216 / 0.28); /* focus ring */ --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.06); --shadow-md: 0 4px 16px rgb(15 23 42 / 0.08); --shadow-lg: 0 12px 32px rgb(15 23 42 / 0.12); --hero-scrim: linear-gradient(90deg, rgb(15 23 42 / 0.92) 0%, rgb(15 23 42 / 0.72) 42%, rgb(15 23 42 / 0.30) 100%); ``` --- ## 2. Tipografi ### 2.1 Font pair | Peran | Font | Sumber | |---|---|---| | Display + body | **Plus Jakarta Sans** | Self-hosted woff2 (`assets/fonts/`) | | Angka / kode order | **JetBrains Mono** | Self-hosted woff2 (`assets/fonts/`) | Keduanya di-host lokal (tanpa CDN) β render deterministik, tidak bergantung jaringan pihak ketiga. ### 2.2 Skala | Token | Ukuran | Line-height | Weight | Tracking | |---|---:|---:|---:|---:| | `--fs-display` | 48px | 1.08 | 800 | -0.03em | | `--fs-h1` | 36px | 1.15 | 800 | -0.025em | | `--fs-h2` | 28px | 1.2 | 700 | -0.02em | | `--fs-h3` | 22px | 1.3 | 700 | -0.015em | | `--fs-lg` | 18px | 1.45 | 600 | -0.01em | | `--fs-body` | 16px | 1.6 | 400 | 0 | | `--fs-sm` | 14px | 1.5 | 400 | 0 | | `--fs-caption` | 13px | 1.45 | 500 | 0.01em | ### 2.3 Aturan angka - Semua kolom **numerik / rupiah / ID order / kode** β `font-variant-numeric: tabular-nums` + JetBrains Mono. - Angka rupiah format Indonesia: `Rp 25.000` (titik ribuan, tanpa desimal untuk rupiah bulat). - Label uang: prefiks `Rp` terpisah dari nominal, dipisah spasi normal (bukan spasi tipografis / non-breaking yang bikin salin-paste error). --- ## 3. Spasi & Radius | Token | Nilai | Pemakaian | |---|---|---| | `--sp-1` | 4px | Icon gap | | `--sp-2` | 8px | Labelβvalue | | `--sp-3` | 12px | Button internal | | `--sp-4` | 16px | Grid gap, padding kartu | | `--sp-5` | 24px | Section inner | | `--sp-6` | 32px | Card padding besar | | `--sp-8` | 48px | Section spacing | | `--sp-12` | 64px | Section spacing mobile | | `--radius-sm` | 6px | Badge, chip | | `--radius-md` | 10px | Input, button | | `--radius-lg` | 16px | Kartu | | `--radius-xl` | 24px | Hero, modal | **Grid:** 8px base. Breakpoint: `640 / 768 / 1024 / 1280 / 1440`. --- ## 4. Komponen Inti ### 4.1 Button | Varian | Background | Teks | Border | |---|---|---|---| | `primary` | `--brand-strong` | `#FFFFFF` | β | | `primary-hover` | `--brand` | `#FFFFFF` | β | | `secondary` | `#FFFFFF` | `--brand` | `--line` | | `ghost` | transparent | `--brand` | β | | `danger` | `#B91C1C` | `#FFFFFF` | β | | `accent` | `--accent` | `--ink` | β | | `nav-outline` | transparent | `#FFFFFF` | `rgba(255,255,255,.45)` β CTA di topbar | - Radius `--radius-md`, padding `12px 20px`, weight 700, font-size `--fs-sm`. - Min touch target **44Γ44px** (mobile), height desktop 44px. - Fokus: `box-shadow: var(--ring)` + `outline: 2px solid transparent`. - **Aturan hierarki CTA:** dalam satu viewport hanya boleh ada **satu** filled amber. CTA topbar = variant `nav-outline` (bukan amber filled) supaya tidak bersaing dengan CTA utama hero. ### 4.2 Input - Border `--line` 1px, radius `--radius-md`, padding `12px 14px`, font-size `--fs-body`. - Fokus: border `--brand-strong` + `box-shadow: var(--ring)`. - Label selalu di atas (bukan placeholder-as-label). Helper text 13px `--ink-2` di atas `--surface`. - Error: border `#B91C1C` + pesan 13px `#B91C1C` (rasio 6.30:1 di putih β ). ### 4.3 Table - Header: `--surface-2`, weight 700, 13px uppercase-ish tracking, `--ink-2`. - Baris zebra: baris genap `--surface-2`. - Border bawah `--line`, **tanpa** border vertikal (baca tabel lebih bersih). - **Kolom numerik rata kanan** + `tabular-nums` + JetBrains Mono. - Mobile: horizontal scroll (`overflow-x:auto`) dengan `min-width` tabel β **bukan** hide kolom. ### 4.4 Badge status - Padding `3px 10px`, radius `--radius-sm`, font-size 12px, weight 700, `letter-spacing: 0.02em`. - Teks = token derived Β§1.3 (dark ink) di atas tint-nya. - **DILARANG** token PRD langsung sebagai warna teks badge. - Dot indikator 6px + label teks (bukan warna saja β aksesibilitas). ### 4.5 Alert | Level | Border | Background | Judul (ink) | |---|---|---|---| | Info | `#075985` | `#F0F9FF` | `#075985` | | Sukses | `#047857` | `#ECFDF5` | `#047857` | | Warning | `#92400E` | `#FFFBEB` | `#92400E` | | Error | `#B91C1C` | `#FEF2F2` | `#B91C1C` | Border kiri 3px solid + ikon Lucide + judul bold + 1 baris body. ### 4.6 Modal - Overlay `rgb(15 23 42 / 0.6)` + `backdrop-filter: blur(4px)`. - Panel radius `--radius-xl`, padding `--sp-6`, shadow `--shadow-lg`. - Fokus di-trap, `Esc` tutup, klik backdrop tutup. ### 4.7 Card - Background `--surface`, border 1px `--line`, radius `--radius-lg`, shadow `--shadow-sm`. - Hover (kartu produk): shadow `--shadow-md` + `translateY(-2px)`. ### 4.8 Stepper status (Lacak Pesanan) - 4 tahap ringkas: `Dibuat β Bayar β Konfirmasi β Selesai`. - Bar 4px, radius penuh. `is-done` β `--ok-ink`, `is-current` β `--brand`, sisanya `--line`. - Label 11px bold; `is-current` pakai `--brand` (bukan `--ink-2`). - Pasangan: status hero (judul + countdown) DI ATAS ringkasan order β user harus langsung tahu "saya di tahap mana". ### 4.9 Status hero - Kartu utama: judul status (`--fs-h3`), sub-info Order ID + waktu, countdown expire. - Countdown: mono + tabular-nums, `--warn-ink` di `--warn-tint`, whitespace nowrap. - Countdown wajib hidup (detik), bukan angka statis. ### 4.10 Panel pembayaran (satu sumber nominal) - **SATU panel** untuk nominal + kode unik. Nominal **tidak boleh** diulang di 3 tempat dengan 3 gaya berbeda (anti-kebingungan + anti-kesalahan baca). - Nominal: mono, tabular-nums, `--fs-h1`, weight 800, warna `--ink`. - Kode unik: mono, tabular-nums, `--fs-h2`, weight 800, tracking 0.1em, warna `--err-ink` (dipakai sebagai **highlight**, bukan error state β tidak boleh tanpa konteks error). - **Copy button WAJIB** untuk nominal dan kode (PRD K-23). State setelah klik: teks `Tersalin` + ikon centang, revert setelah 1.8 detik. - Copy button = target sentuh 44px, bukan 36px. --- ## 5. Ikon - **Lucide** (MIT), stroke 2px, 24Γ24 viewBox, `currentColor`. - 40 ikon sudah di-cache lokal di `assets/icons/*.svg` β **inline SVG**, bukan font-icon, bukan hand-rolled path. - Ikon dekoratif β `aria-hidden="true"`. Ikon yang punya makna β `aria-label` + `