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
103 changes: 22 additions & 81 deletions docs/design/gen.mjs
Original file line number Diff line number Diff line change
@@ -1,88 +1,30 @@
// Generator preview 3 opsi warna Dockify (S0). Hasil: preview-warna.html (statis, tanpa JS, font data URI) + kontras.md.
// Generator preview 3 palet Dockify (nilai token dari docs/DESIGN-SYSTEM.md §3). Hasil: preview-warna.html (statis, tanpa JS, font data URI) + kontras.md.
// Jalankan: node gen.mjs (butuh akses ke fonts.googleapis.com untuk menanam font)
import { writeFileSync } from "node:fs";
import { readFileSync, writeFileSync } from "node:fs";

// ---------- Token lapis 2 per opsi (nama persis standar §3) ----------
// ---------- Token lapis 2 per opsi: dibaca dari docs/DESIGN-SYSTEM.md §3 (sumber tunggal nilai final) ----------
const DS = readFileSync(new URL("../DESIGN-SYSTEM.md", import.meta.url), "utf8");
function palet(slug) {
const sec = DS.split(/^### /m).find((x) => x.startsWith(`3.`) && x.includes("`" + slug + "`"));
if (!sec) throw new Error(`palet ${slug} tidak ada di DESIGN-SYSTEM.md §3`);
const light = {}, dark = {};
for (const m of sec.matchAll(/^\| ([a-z0-9-]+) \| `([^`]+)` \| `([^`]+)` \|$/gm)) [light[m[1]], dark[m[1]]] = [m[2], m[3]];
return { light, dark };
}
const OPSI = [
{
id: "1",
nama: "1 · Indigo Dockify",
catatan: "Brand Dockify sekarang (indigo) dirapikan: netral slate, indigo untuk aksi utama, teal untuk Deploy App. Paling akrab bagi pengguna lama.",
light: {
bg: "#f5f7fb", surface: "#ffffff", sunk: "#f1f4f9", line: "#e2e8f0", "line-strong": "#cbd5e1", control: "#7a8699",
ink: "#0f172a", ink2: "#334155", muted: "#5b677a",
accent: "#4f46e5", "accent-fill": "#4f46e5", "on-accent": "#ffffff", "accent-soft": "#eef0ff",
"brand2-fill": "#14b8a6", "on-brand2": "#042f2e", brand2: "#0f766e", "brand2-soft": "#dcf5f1",
chart: "#6366f1", "chart-soft": "#e3e5fc"
},
dark: {
bg: "#0b1020", surface: "#151b2e", sunk: "#0f1426", line: "#262e48", "line-strong": "#36405f", control: "#6e7a9c",
ink: "#e8ebf5", ink2: "#c0c7dc", muted: "#929bb8",
accent: "#a5b4fc", "accent-fill": "#5850ec", "on-accent": "#ffffff", "accent-soft": "#252a55",
"brand2-fill": "#2dd4bf", "on-brand2": "#042f2e", brand2: "#5eead4", "brand2-soft": "#103633",
chart: "#818cf8", "chart-soft": "#252a55"
}
},
{
id: "2",
nama: "2 · Navy Brosur",
catatan: "Palet contoh standar (hadir): navy tua untuk aksi, oranye untuk Deploy App, teal untuk grafik CPU/RAM/Disk. Paling hangat dan berkarakter.",
light: {
bg: "#eef1f8", surface: "#ffffff", sunk: "#f5f7fc", line: "#e1e5f0", "line-strong": "#c8cede", control: "#7c83ad",
ink: "#141a33", ink2: "#3d4566", muted: "#656d8c",
accent: "#2b3486", "accent-fill": "#2b3486", "on-accent": "#ffffff", "accent-soft": "#e7e9f8",
"brand2-fill": "#f26a21", "on-brand2": "#1b1f3b", brand2: "#c2410c", "brand2-soft": "#fdeee4",
chart: "#178a8c", "chart-soft": "#dff3f3"
},
dark: {
bg: "#0c0f1e", surface: "#161a2f", sunk: "#11142a", line: "#272c48", "line-strong": "#363c5e", control: "#6b7399",
ink: "#e9ebf7", ink2: "#bfc4de", muted: "#8f95b4",
accent: "#a9b2ff", "accent-fill": "#4a54c9", "on-accent": "#ffffff", "accent-soft": "#242a5c",
"brand2-fill": "#f26a21", "on-brand2": "#1b1f3b", brand2: "#ff9a5c", "brand2-soft": "#3a2418",
chart: "#4fd1d3", "chart-soft": "#143339"
}
},
{
id: "3",
nama: "3 · Slate Teal Ops",
catatan: "Netral abu-biru dingin, teal gelap untuk aksi, amber untuk Deploy App. Kesan layar monitoring: tenang, status dan angka paling menonjol.",
light: {
bg: "#f0f3f5", surface: "#ffffff", sunk: "#f3f6f8", line: "#dde3e8", "line-strong": "#c5cfd7", control: "#74828f",
ink: "#0f1a22", ink2: "#34434f", muted: "#5b6975",
accent: "#0e6e78", "accent-fill": "#0e6e78", "on-accent": "#ffffff", "accent-soft": "#e0f1f2",
"brand2-fill": "#f5a524", "on-brand2": "#1a1305", brand2: "#a35a00", "brand2-soft": "#fdf0d9",
chart: "#0891b2", "chart-soft": "#dcf0f6"
},
dark: {
bg: "#0a1116", surface: "#131c23", sunk: "#0e161c", line: "#22303a", "line-strong": "#314350", control: "#687b89",
ink: "#e6eef2", ink2: "#b9c8d1", muted: "#8a9ba7",
accent: "#5fd4dd", "accent-fill": "#0e6e78", "on-accent": "#ffffff", "accent-soft": "#103338",
"brand2-fill": "#f5a524", "on-brand2": "#1a1305", brand2: "#f8b95a", "brand2-soft": "#33270f",
chart: "#38bdf8", "chart-soft": "#0f2c3a"
}
}
{ id: "1", nama: "1 · Indigo Dockify (default)", catatan: "Netral slate, indigo untuk semua aksi utama (termasuk Deploy App), violet untuk seri grafik kedua.", ...palet("indigo") },
{ id: "2", nama: "2 · Navy Brosur", catatan: "Navy tua untuk aksi, biru untuk seri grafik kedua, grafik indigo-navy. Paling formal.", ...palet("navy") },
{ id: "3", nama: "3 · Slate Teal Ops", catatan: "Netral abu-biru dingin, teal gelap untuk aksi, biru langit untuk seri kedua. Kesan layar monitoring.", ...palet("teal") }
];

// Token status sama di semua opsi (kontras tetap dihitung per opsi karena surface berbeda).
const SEM = {
light: {
ok: "#15803d", "ok-text": "#166534", "ok-bg": "#dcfce7",
warn: "#b45309", "warn-text": "#92400e", "warn-bg": "#fef3c7",
danger: "#c81e1e", "danger-text": "#991b1b", "danger-bg": "#fee2e2", "danger-fill": "#c81e1e",
shadow: "0 1px 2px rgba(16,24,40,.06),0 1px 3px rgba(16,24,40,.05)"
},
dark: {
ok: "#4ade80", "ok-text": "#86efac", "ok-bg": "#10301e",
warn: "#fbbf24", "warn-text": "#fcd34d", "warn-bg": "#33270a",
danger: "#f87171", "danger-text": "#fca5a5", "danger-bg": "#3b1618", "danger-fill": "#c81e1e",
shadow: "0 1px 2px rgba(0,0,0,.45)"
}
};

const ORDER = ["bg", "surface", "sunk", "line", "line-strong", "control", "ink", "ink2", "muted", "accent", "accent-fill", "on-accent", "accent-soft",
"brand2-fill", "on-brand2", "brand2", "brand2-soft", "chart", "chart-soft", "ok", "ok-text", "ok-bg", "warn", "warn-text", "warn-bg",
"danger", "danger-text", "danger-bg", "danger-fill", "shadow"];
const tok = (o, mode) => ({ ...o[mode], ...SEM[mode] });
const tok = (o, mode) => o[mode];
for (const o of OPSI) for (const mode of ["light", "dark"]) {
const miss = ORDER.filter((k) => !o[mode][k]);
if (miss.length) throw new Error(`opsi ${o.id} ${mode}: token hilang ${miss.join(", ")}`);
}

// ---------- Kontras WCAG ----------
const lum = (hex) => {
Expand Down Expand Up @@ -194,7 +136,7 @@ const dashboard = (dark) => `${header(dark)}

const apps = (dark) => `${header(dark)}
<main class="body">
<div class="titlerow"><h1>Apps</h1><span class="btn btn-brand">${ic("plus")}Deploy App</span></div>
<div class="titlerow"><h1>Apps</h1><span class="btn btn-primary">${ic("plus")}Deploy App</span></div>
<label class="input">${ic("search")}<span>Filter by name or domain</span></label>
<div class="chips"><span class="chip on" aria-pressed="true">All</span><i class="vsep"></i><span class="chip">running</span><span class="chip">stopped</span><span class="chip">draft</span></div>
<p class="meta">3 apps on 2 servers</p>
Expand Down Expand Up @@ -316,7 +258,6 @@ h1{font-size:22px;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.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 .icon{width:17px;height:17px}
.btn-primary{background:var(--accent-fill);color:var(--on-accent);box-shadow:var(--shadow)}
.btn-brand{background:var(--brand2-fill);color:var(--on-brand2)}
.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}
Expand Down Expand Up @@ -388,9 +329,9 @@ const desktop = (o) => `<section class="opt"><h2>Pola ResponsiveSheet di desktop
</div></div></section>`;

const html = (fonts) => `<!doctype html><html lang="id"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Dockify · 3 opsi warna</title>
<title>Dockify · 3 palet</title>
<style>${fonts}${CSS}</style></head><body><div class="page">
<h1>Dockify: pilih 1, 2, atau 3</h1>
<h1>Dockify: tiga palet (Settings → Appearance)</h1>
<p class="lead">Semua kontras sudah dihitung (WCAG, terang dan gelap): teks ≥4.5:1, batas kontrol ≥3:1, <b>semua pasangan lolos</b> (${OPSI.map((o) => `opsi ${o.id}: ${lolos(o.id)}`).join(", ")}).</p>
<p class="lead">Struktur sama di ketiga opsi; yang berbeda hanya warna. Tiap layar: HP 360px, terang dan gelap berdampingan. Isi dari data mock Dockify (prod-heavy-1, staging-1, web-shop, api-core, worker-mail). Aksi berbahaya merah garis di zona bahaya, isian merah hanya di konfirmasi (K9). Label UI tetap bahasa Inggris.</p>
${OPSI.map((o) => `<section class="opt"><h2>${o.nama}</h2><p>${o.catatan}</p>
Expand Down
14 changes: 7 additions & 7 deletions docs/design/kontras.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Ringkasan: opsi 1 38/38 lolos · opsi 2 38/38 lolos · opsi 3 38/38 lolos (12 pa

Lencana Dockify: running/online = ok (`ok-bg` + `ok-text`); pending/initializing/deploying = warn (`warn-bg` + `warn-text`); stopped/draft = netral (`sunk` + `ink2`, garis `line`); error/failed/offline = danger (`danger-bg` + `danger-text`).

## Opsi 1 · Indigo Dockify
## Opsi 1 · Indigo Dockify (default)

| Pasangan | Min | Terang | Gelap | Catatan |
| :--- | ---: | ---: | ---: | :--- |
Expand All @@ -21,13 +21,13 @@ Lencana Dockify: running/online = ok (`ok-bg` + `ok-text`); pending/initializing
| danger-text / danger-bg | 4.5 | 6.80 | 8.42 | |
| ok-text / ok-bg | 4.5 | 6.49 | 10.22 | |
| warn-text / warn-bg | 4.5 | 6.37 | 10.15 | |
| on-brand2 / brand2-fill | 4.5 | 5.81 | 7.77 | |
| on-brand2 / brand2-fill | 4.5 | 7.10 | 7.10 | |
| muted / bg | 4.5 | 5.34 | 6.85 | meta di latar halaman |
| accent / accent-soft | 4.5 | 5.55 | 6.84 | chip aktif |
| ink2 / sunk | 4.5 | 9.39 | 10.84 | lencana netral |
| ok / surface | 4.5 | 5.02 | 9.81 | angka KPI Online/Running |
| white / danger-fill | 4.5 | 5.74 | 5.74 | tombol Undeploy di konfirmasi |
| brand2 / surface | 4.5 | 5.47 | 11.56 | angka sekunder |
| brand2 / surface | 4.5 | 7.10 | 9.26 | angka sekunder |
| chart / chart-soft | 3 | 3.59 | 4.57 | bar CPU/RAM/Disk (grafis) |

| Token | Terang | Gelap |
Expand Down Expand Up @@ -78,13 +78,13 @@ Lencana Dockify: running/online = ok (`ok-bg` + `ok-text`); pending/initializing
| danger-text / danger-bg | 4.5 | 6.80 | 8.42 | |
| ok-text / ok-bg | 4.5 | 6.49 | 10.22 | |
| warn-text / warn-bg | 4.5 | 6.37 | 10.15 | |
| on-brand2 / brand2-fill | 4.5 | 5.25 | 5.25 | |
| on-brand2 / brand2-fill | 4.5 | 8.72 | 8.72 | |
| muted / bg | 4.5 | 4.51 | 6.46 | meta di latar halaman |
| accent / accent-soft | 4.5 | 8.98 | 6.73 | chip aktif |
| ink2 / sunk | 4.5 | 8.74 | 10.51 | lencana netral |
| ok / surface | 4.5 | 5.02 | 9.85 | angka KPI Online/Running |
| white / danger-fill | 4.5 | 5.74 | 5.74 | tombol Undeploy di konfirmasi |
| brand2 / surface | 4.5 | 5.18 | 8.20 | angka sekunder |
| brand2 / surface | 4.5 | 8.72 | 9.52 | angka sekunder |
| chart / chart-soft | 3 | 4.96 | 5.08 | bar CPU/RAM/Disk (grafis) |

| Token | Terang | Gelap |
Expand Down Expand Up @@ -135,13 +135,13 @@ Lencana Dockify: running/online = ok (`ok-bg` + `ok-text`); pending/initializing
| danger-text / danger-bg | 4.5 | 6.80 | 8.42 | |
| ok-text / ok-bg | 4.5 | 6.49 | 10.22 | |
| warn-text / warn-bg | 4.5 | 6.37 | 10.15 | |
| on-brand2 / brand2-fill | 4.5 | 9.03 | 9.03 | |
| on-brand2 / brand2-fill | 4.5 | 7.56 | 7.56 | |
| muted / bg | 4.5 | 5.06 | 6.63 | meta di latar halaman |
| accent / accent-soft | 4.5 | 5.12 | 7.70 | chip aktif |
| ink2 / sunk | 4.5 | 9.38 | 10.65 | lencana netral |
| ok / surface | 4.5 | 5.02 | 9.89 | angka KPI Online/Running |
| white / danger-fill | 4.5 | 5.74 | 5.74 | tombol Undeploy di konfirmasi |
| brand2 / surface | 4.5 | 5.22 | 9.92 | angka sekunder |
| brand2 / surface | 4.5 | 7.56 | 10.34 | angka sekunder |
| chart / chart-soft | 3 | 3.13 | 6.80 | bar CPU/RAM/Disk (grafis) |

| Token | Terang | Gelap |
Expand Down
75 changes: 37 additions & 38 deletions docs/design/preview-warna.html

Large diffs are not rendered by default.

Loading