Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/DESIGN-SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ Lencana: 10 sampai 11px, 800, huruf kapital, radius 6, font mono untuk nilai tek
## 4. Tipografi, spasi, radius
Body 15px/1.5. KPI 24px/800 tracking -0.02em. Angka sekunder 20px/800. Judul kartu 15px/700. Label 12.8px. Meta/chip 11 sampai 12px (chip 600).
Label tab bawah 11px. Input/select **16px**. Skala spasi 4px: padding halaman 14 sampai 16px, antar kartu 12px, antar kontrol 8px.
Radius: kartu 16, kontrol/tombol 12, lencana 6, chip/pill penuh. Target sentuh aksi utama dan toggle ≥44px; chip 32px dengan jarak ≥6px.
Radius: kartu 16, kontrol/tombol 12, lencana 6, chip/pill penuh. Skala kontrol (dikecilkan dari 44/48, mengikuti hadir S16): input/select/tombol default **40px**, `sm` 34px, `lg` 44px (satu aksi utama penuh-lebar), ikon 40px (`btn-icon`) dan 36px (`btn-icon-sm`), nav desktop 40px, segmen HP 38px. Teks input 16px di HP (iOS zoom), 14px di ≥700px. Chip 32px dengan jarak ≥6px.

## 5. Komponen (partial bersama, varian di partial bukan di pemakaian)
| Kebutuhan | Partial / kelas | Catatan |
| :--- | :--- | :--- |
| Tombol | `.btn` + varian `primary` `secondary` `ghost` `destructive` `destructive-outline` `link`; ukuran 44 (default) / 36 (`sm`) / 48 (`lg`); ikon 44/40 | satu `primary` per layar/panel; dalam satu kelompok varian harus berbeda |
| Input + label | `.field` (label 12.8px/600 + input 16px, border `control`, fokus outline 3px `accent`) | tanpa titik dua di label |
| Tombol | `.btn` + varian `primary` `secondary` `ghost` `destructive` `destructive-outline` `link`; ukuran 40 (default) / 34 (`sm`) / 44 (`lg`); ikon 40/36 | satu `primary` per layar/panel; dalam satu kelompok varian harus berbeda |
| Input + label | `.field` (label 12.8px/600 + input 16px HP, 14px desktop, tinggi 40, border `control`, fokus outline 3px `accent`) | tanpa titik dua di label |
| Select | `<select class="select">` native digayakan + chevron SVG | penyimpangan K4 yang disetujui |
| Dialog / alert-dialog / drawer | `ui_sheet`: `<dialog class="sheet">` + `openSheet(id)`/`closeSheet(id)`; ≥700px popup tengah max-w 560 radius 16 max-h 86dvh; <700px panel bawah max-w 560 radius atas 16 handle 40×4 max-h 92dvh + safe-area; animasi ≤240 ms; hormati `prefers-reduced-motion`; tutup via X, backdrop, Escape; **tanpa tautan "Tutup" di bawah** | menggantikan semua `confirm()` dan modal inline |
| Kartu | `.card` = `surface` + border `line` + `shadow`, radius 16 | bayangan hanya di sini |
Expand All @@ -164,8 +164,8 @@ Radius: kartu 16, kontrol/tombol 12, lencana 6, chip/pill penuh. Target sentuh a

## 6. Layout
- Mobile first 360×740, uji 390×844 dan 1280×800. Tanpa overflow horizontal halaman (hanya baris chip).
- Shell: header ringkas (logo + nama + tombol ikon 44px: tema, keluar) + **tab bar bawah** <900px (Dashboard, Servers, Apps, Settings; ikon + label 11px, garis aktif, `aria-current`, `env(safe-area-inset-bottom)`). ≥900px: tab pindah ke bawah header, konten max 1100px, kartu grid 2 kolom. About pindah ke Settings.
- Daftar: <700px baris kartu (grid `minmax(0,1.3fr) 1fr 1fr 44px`, `white-space:nowrap`), ≥700px tabel. KPI grid 2×2 di HP, 4 kolom di desktop.
- Shell: header ringkas (logo + nama + tombol ikon 40px: tema, keluar) + **tab bar bawah** <900px (Dashboard, Servers, Apps, Settings; ikon + label 11px, garis aktif, `aria-current`, `env(safe-area-inset-bottom)`). ≥900px: tab pindah ke bawah header, konten max 1100px, kartu grid 2 kolom. About pindah ke Settings.
- Daftar: <700px baris kartu (grid `minmax(0,1.3fr) 1fr 1fr 36px`, `white-space:nowrap`), ≥700px tabel. KPI grid 2×2 di HP, 4 kolom di desktop.
- Panel detail: header (nama 18/800 + meta 12.8 muted + X) → banner status → `detail-grid` 2 kolom (dt 11/800 kapital muted, dd 14/600) → seksi berjudul (12.8/800 kapital, garis atas) → aksi (grid 2 kolom, primary penuh lebar) → zona bahaya.

## 7. Performa dan aksesibilitas (diukur, `tests/e2e/ui.mjs`)
Expand Down
4 changes: 2 additions & 2 deletions docs/design/gen.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,14 @@ h1{font-size:22px;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.tab.on{color:var(--accent)}
.tab.on::before{content:"";position:absolute;top:0;left:26%;right:26%;height:3px;border-radius:0 0 3px 3px;background:var(--accent)}
.titlerow{display:flex;justify-content:space-between;align-items:center;gap:8px}
.btn{height:44px;border-radius:12px;padding:0 16px;display:flex;align-items:center;justify-content:center;gap:7px;font-weight:700;font-size:14px;white-space:nowrap}
.btn{height:40px;border-radius:12px;padding:0 16px;display:flex;align-items:center;justify-content:center;gap:7px;font-weight:700;font-size:14px;white-space:nowrap}
.btn .icon{width:17px;height:17px}
.btn-primary{background:var(--accent-fill);color:var(--on-accent);box-shadow:var(--shadow)}
.btn-secondary{background:var(--surface);color:var(--ink);border:1px solid var(--control)}
.btn-ghost{color:var(--ink2)}
.btn-dout{color:var(--danger);border:1.5px solid var(--danger);padding:0 8px;background:transparent}
.btn-destructive{background:var(--danger-fill);color:#fff}
.input{height:44px;border-radius:12px;border:1px solid var(--control);background:var(--surface);display:flex;align-items:center;gap:8px;padding:0 12px;color:var(--muted);font-size:16px}
.input{height:40px;border-radius:12px;border:1px solid var(--control);background:var(--surface);display:flex;align-items:center;gap:8px;padding:0 12px;color:var(--muted);font-size:16px}
.chips{display:flex;gap:6px;align-items:center;margin:0 -16px;padding:0 16px;overflow:hidden}
.chip{flex:none;height:32px;padding:0 12px;border-radius:99px;border:1px solid var(--line-strong);display:flex;align-items:center;font-size:12.5px;font-weight:600;color:var(--ink2)}
.chip.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
Expand Down
31 changes: 16 additions & 15 deletions internal/http/static/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ body:not(.login-page) { padding-bottom: calc(56px + env(safe-area-inset-bottom))
position: static;
display: flex;
gap: 4px;
height: 44px;
height: 40px;
padding: 0 24px;
background: none;
border-top: 0;
Expand Down Expand Up @@ -366,7 +366,7 @@ form .grid { gap: 1.2em; margin-bottom: 0.9em; }
transition: background-color 0.15s ease, border-color 0.15s ease;
line-height: 1.45;
text-decoration: none;
min-height: 44px;
min-height: 40px;
padding: 0 16px;
border-radius: 12px;
font-size: 14px;
Expand All @@ -380,8 +380,8 @@ form .grid { gap: 1.2em; margin-bottom: 0.9em; }
.btn:hover { background: var(--sunk); border-color: var(--control); color: var(--ink); }
.btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-sm { min-height: 36px; padding: 0 12px; font-size: 13px; }
.btn-lg { min-height: 48px; padding: 0 20px; }
.btn-sm { min-height: 34px; padding: 0 12px; font-size: 13px; }
.btn-lg { min-height: 44px; padding: 0 18px; }
.btn-primary, .btn-primary:hover { background: var(--accent-fill); border-color: var(--accent-fill); color: var(--on-accent); }
.btn-primary:hover { filter: brightness(1.1); }
.btn-secondary { background: var(--surface); border-color: var(--control); color: var(--ink); }
Expand All @@ -392,8 +392,8 @@ form .grid { gap: 1.2em; margin-bottom: 0.9em; }
.btn-destructive-outline { background: transparent; border-color: var(--danger); color: var(--danger-text); }
.btn-destructive-outline:hover { background: var(--danger-bg); border-color: var(--danger); color: var(--danger-text); }
.btn-link, .btn-link:hover { background: none; border: 0; min-height: 0; padding: 0; color: var(--accent); text-decoration: underline; }
.btn-icon { width: 44px; padding: 0; }
.btn-icon-sm { width: 40px; min-height: 40px; padding: 0; }
.btn-icon { width: 40px; padding: 0; }
.btn-icon-sm { width: 36px; min-height: 36px; padding: 0; }
.icon { display: block; flex-shrink: 0; }

/* Sheet: popup >= 700px, bottom panel below (DESIGN-SYSTEM §5) */
Expand Down Expand Up @@ -447,7 +447,7 @@ form .grid { gap: 1.2em; margin-bottom: 0.9em; }
.listbar { margin-bottom: 12px; }
.search { position: relative; margin-bottom: 8px; }
.search .icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--muted); pointer-events: none; }
.search input { padding-left: 40px; min-height: 44px; font-size: 16px; }
.search input { padding-left: 40px; }
.chips {
display: flex;
gap: 6px;
Expand Down Expand Up @@ -539,11 +539,11 @@ tbody tr:hover td { background: var(--accent-soft); }
table a { font-weight: 500; color: var(--accent); }
table a:hover { color: var(--ink); text-decoration: underline; }

/* Form elements (DESIGN-SYSTEM §4, §5): 16px controls, 44px high, radius 12, border `control` */
/* Form elements (DESIGN-SYSTEM §4, §5): 16px controls on phones (14px at >= 700px), 40px high, radius 12, border `control` */
input, textarea, select {
font-family: inherit;
font-size: 16px;
min-height: 44px;
min-height: 40px;
padding: 0 12px;
border-radius: 12px;
border: 1px solid var(--control);
Expand Down Expand Up @@ -577,11 +577,11 @@ summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accen
@media (min-width: 700px) { .form-actions { display: flex; } }
.row-grid { display: grid; gap: 8px; margin-bottom: 8px; align-items: start; }
.row-grid > * { min-width: 0; }
.row-domain { grid-template-columns: minmax(0, 1fr) 44px; }
.row-env { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 40px 40px; }
.row-file { grid-template-columns: minmax(0, 1fr) auto 40px; }
.row-domain { grid-template-columns: minmax(0, 1fr) 40px; }
.row-env { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 36px 36px; }
.row-file { grid-template-columns: minmax(0, 1fr) auto 36px; }
.row-grid input, .row-grid textarea { margin: 0; }
.row-env textarea { min-height: 44px; }
.row-env textarea { min-height: 40px; }
.inline-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.opt-group { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.opt-group legend { margin-bottom: 4px; }
Expand Down Expand Up @@ -782,7 +782,7 @@ pre {
.seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--sunk); border-radius: 12px; max-width: 100%; overflow-x: auto; }
.seg-btn { min-height: 32px; padding: 0 12px; border: 0; border-radius: 10px; background: none; box-shadow: none; color: var(--ink2); font-size: 12.8px; font-weight: 600; white-space: nowrap; }
.seg-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
@media (max-width: 699px) { .seg-btn { min-height: 44px; } }
@media (max-width: 699px) { .seg-btn { min-height: 38px; } }
.seg-btn[aria-pressed=true] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
.stats-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.stats-header h3 { margin: 0; display: flex; align-items: center; gap: 8px; }
Expand Down Expand Up @@ -853,10 +853,11 @@ pre.code { margin: 0; padding: 12px; background: var(--sunk); border: 1px solid
.seg-radio span { display: flex; align-items: center; min-height: 32px; padding: 0 16px; border-radius: 10px; font-size: 12.8px; font-weight: 600; color: var(--ink2); }
.seg-radio input:checked + span { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
.seg-radio input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 1px; }
@media (max-width: 699px) { .seg-radio span { min-height: 44px; } }
@media (max-width: 699px) { .seg-radio span { min-height: 38px; } }
.group-title { font-size: 12.8px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink2); margin: 16px 0 4px; }
.page-actions { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 0; }
hgroup .page-actions { margin-top: 4px; }
@media (min-width: 700px) { input, select, textarea { font-size: 14px; } }
/* iOS zooms inputs below 16px: keep mono fields at 16px on phones */
@media (max-width: 699px) { input.mono, textarea.mono, .secret-row input { font-size: 16px; } }
.row-domain > input:only-child { grid-column: 1 / -1; }
Expand Down
Loading