Prisma

🎯 New Showcase Workflow

Quy trình tạo 1 showcase app mới dùng Prisma Design System.

Quick navigation:


Pre-read (BẮT BUỘC)

  1. .agent/skills/style-scaling/SKILL.md§1 Design Intent Extraction (3-axis)
  2. .agent/skills/ux-research/SKILL.md§6 Typography (T1 font ≥14px), §7 A11y (ARIA, focus), §5 Component (states, keyboard)
  3. CSS Naming Rules bên dưới
  4. design-system/components md/ATOMIC-MAPPING.md — Component → token mapping (4-tier: page/section/group/comp)
  5. knowledge/stacking-design-methodology.md§2 Padding Nesting (page > section > group > comp), §8 Slot Anatomy (--_slot-padding bridge)
  6. knowledge/container-padding-rules.md§3 Gap Model, §4 Rules P1-P6 (uniform padding, slot ownership)
  7. knowledge/divider-separator-rules.md§7 Rules D1-D9 (spacing > divider > border)
  8. knowledge/research/density-formula.md — Tier-base multipliers, density presets, showcase config integration

Steps

// turbo-all

1. Design Intent Extraction

Chạy §1 Design Intent Extraction từ style-scaling skill:

text
DESIGN INTENT EXTRACTION:
- Client/Project : _______________
- Brand color    : #XXXXXX → palette candidate: {color-name}
- Secondary color: #XXXXXX | reuse {existing} | none
- Neutral base   : zinc | slate | stone | gray | warm
- Density axis   : comfortable | compact | default | custom
- Visual axis    : default | glass/liquid | minimal | custom(___)
- Font candidate : Inter | Roboto | system | custom(___)
- Tone           : conservative | playful | enterprise | consumer | fintech
- Brand exists?  : YES (dùng themes/{existing}) | NO (tạo mới)
- Style-mode?    : [tên preset] | cần tạo mới

→ Output này quyết định mọi thứ phía sau.

2. Tạo thư mục + pipeline config

bash
mkdir showcase\{name}

Thêm entry vào design-system/scripts/config/showcase-config.json → xem format tại Pipeline Config

Density config — chọn preset hoặc custom:

json
"density": "comfortable"    // preset: compact | comfortable | spacious | mobile | mobile-compact
// hoặc custom:
"density": { "spacing": "3px", "profile": "web", "tier-bases": { "group": 3 } }

→ Xem chi tiết presets tại knowledge/research/density-formula.md §Showcase Config Integration

3. Generate variables.css

bash
node design-system/scripts/pipeline/sync-tokens.js {name}

→ Output: showcase/{name}/variables.css (563+ tokens, ~58KB)

4. Elevation Map — GÁN LAYER CHO MỌI COMPONENT

📖 ĐỌC CSS Naming Rules TRƯỚC.

Output bắt buộc — liệt kê MỌI component, gán layer + density tier, lock tokens:

text
ELEVATION MAP: {Tên showcase}
┌────────────────────┬───────────┬──────────┬──────────────────────────────────────┐
│ Component          │ Layer     │ Tier     │ Tokens (locked)                      │
├────────────────────┼───────────┼──────────┼──────────────────────────────────────┤
│ ground-header      │ Ground    │ page     │ bg: --background, fg: --foreground   │
│ ground-hero        │ Ground    │ page     │ bg: --background, fg: --foreground   │
│ card-account       │ Card      │ section  │ bg: --card, fg: --card-foreground    │
│ card-{feature}     │ Card      │ group    │ bg: --card, fg: --card-foreground    │
│ item-{name}        │ Item      │ comp     │ (inherits from parent layer)         │
│ btn--primary       │ Item      │ comp     │ bg: --primary, fg: --primary-fg      │
│ surface-nav        │ Surface   │ section  │ bg: --surface, fg: --surface-fg      │
│ surface-toast      │ Surface   │ comp     │ bg: --surface, fg: --surface-fg      │
└────────────────────┴───────────┴──────────┴──────────────────────────────────────┘

TIER ASSIGNMENT RULES:
  Card ON page → section tier (--section-*)
  Card INSIDE section → group tier (--group-*)
  Inline item → comp tier (--comp-*)

⚠️ DỪNG LẠI — User phải approve Elevation Map này TRƯỚC KHI viết CSS.

Sau khi approve:

  • Mỗi ground-* class → BẮT BUỘC background: var(--background) hoặc var(--canvas)
  • Mỗi card-* class → BẮT BUỘC background: var(--card)
  • Mỗi surface-* class → BẮT BUỘC background: var(--surface)
  • KHÔNG hardcode rgba(...), #hex cho bg/fg/border
  • backdrop-filter, decorative gradients → OK hardcode

5. Tạo HTML

BẮT BUỘC có:

html
<link rel="stylesheet" href="variables.css">
<link rel="stylesheet" href="{app}.css">

HTML class names PHẢI theo elevation map từ Step 4.

6. Tạo CSS + JS

PRE-CODE CHECKLIST (verify trước khi viết CSS):

Rule Check
STACK page.padding > section.padding > group.padding > comp.padding?
GAP Card dùng Gap Model (container gap, slots không overlap padding)?
SLOT Slots dùng --_slot-padding bridge (không hardcode --group-padding-default)?
PLCHLD Placeholder margin: 0 (slot owns padding, placeholder không thêm margin)?
P2 padding-inline = padding-block (uniform)?
D1 Dùng spacing (gap/margin) thay vì border divider?
D6 Không divider giữa các cards?
D9/S8 Không border-top/bottom bên trong card/dialog/drawer?
D5 Divider margin >= var(--spacing-4)?
S9 Content trong slot-body KHÔNG thêm padding inline?
NAMING Class names có elevation prefix (ground-/card-/surface-)?
Token Mọi bg/fg/spacing/radius dùng var(--token)?
TIER Spacing/padding/radius tokens match tier assignment (page/section/group/comp)?
SLOT-MAP Structural components dùng data-slot attributes? (ENF-6)
SLOT-NAME Slot names lấy từ slot-manifest.json, KHÔNG tự tạo? (ENF-6)

7. Validate → chạy /post-change

8. Visual test

text
http://localhost:3000/showcase/{name}/

Quy tắc

  1. variables.css luôn từ pipeline — KHÔNG copy từ docs/ hay showcase/ khác
  2. HTML link localhref="variables.css" (không ../../docs/assets/...)
  3. Mọi CSS value dùng tokens — trừ decorative animations (aurora, orbs, shimmers)
  4. 1 showcase = 1 entry trong design-system/scripts/config/showcase-config.json
  5. CSS class names theo elevationground-/card-/surface- prefix bắt buộc
  6. Không đặt tên theo business data — tên = vai trò UI
  7. Component mapping từ ATOMIC-MAPPING.md — đọc trước khi dùng token
  8. Sau mọi thay đổi → chạy /post-change → ghi /dev-journal
  9. Density tier tokens = 4 cấppage > section > group > comp (KHÔNG dùng block/module/item)


📎 Appendix A — Pipeline Config

Showcase Config Entry

Thêm entry vào design-system/scripts/config/showcase-config.jsonshowcases object:

json
"{name}": {
    "description": "{mô tả}",
    "tokensDir": "../../design-system/tokens",
    "outputDir": "showcase/{name}",
    "defaultBrand": "{brand từ Design Intent}",
    "density": "comfortable",
    "styleFallbacks": {
        "light": {
            "--transition-fast": "0.15s ease-in-out",
            "--transition-normal": "0.25s ease-in-out",
            "--shadow-sm": "...",
            "--shadow-md": "...",
            "--shadow-lg": "...",
            "--gradient-primary": "..."
        },
        "dark": {}
    }
}

Reference Showcases

Existing showcases in showcase-config.json làm tham khảo:

  • nab-open-banking — NAB SME dark theme, comfortable density
  • banking-liquid-style — Premium banking, mobile density

CSS Authoring Guide

Dùng DS tokens trực tiếp (default style):

  • Colors: var(--primary), var(--foreground), var(--muted-foreground)
  • Spacing: var(--{tier}-padding-{size}), var(--{tier}-stack-gap-{size})
  • Radius: var(--comp-radius), var(--section-radius-default), var(--group-radius-default)
  • Components: var(--card), var(--card-border), var(--surface)
  • KHÔNG hardcode giá trị — luôn dùng var(--token-name)

Density tier token pattern:

css
/* Page-level (outermost) */
padding: var(--page-padding-default);
gap: var(--page-stack-gap-default);

/* Section (content region) */
padding: var(--section-padding-default);
gap: var(--section-stack-gap-default);
border-radius: var(--section-radius-default);

/* Group (card/panel) */
padding: var(--group-padding-default);
gap: var(--group-stack-gap-default);
border-radius: var(--group-radius-default);

/* Comp (button/input/item) */
padding: var(--comp-padding-default);
gap: var(--comp-stack-gap-default);
border-radius: var(--comp-radius);

Icons — SVG Only (IC-1/IC-2/IC-3)

  • ALL icons MUST be SVG — use <svg><use href="#ic-name"/></svg> from the icon sprite
  • NEVER use text characters as icons: ✕ × ▼ ▾ → ← ↑ ↓ ‹ › + are FORBIDDEN
  • Close buttons: <svg class="icon--sm" aria-hidden="true"><use href="#ic-x"/></svg>
  • Chevrons: Use SVG chevron icons or CSS transform: rotate() on SVG
  • Decorative icons: add aria-hidden="true"
  • Icon-only buttons: require aria-label for accessibility

Utility Classes

  • Do NOT create ad-hoc utility classes like .gap-xs, .gap-sm
  • Use tokens directly in component CSS: gap: var(--comp-stack-gap-small)
  • If utility classes are needed, name must reflect tier + axis: .gap-comp-stack-sm

Validation Pipeline

bash
node design-system/scripts/pipeline/sync-tokens.js --all
node design-system/scripts/docs/build-docs.js
node design-system/scripts/pipeline/lint-css.js --all
node design-system/scripts/pipeline/verify-output.js

→ Phải đạt 0 errors



📎 Appendix B — CSS Class Naming (Elevation-Based Convention)

Quy chuẩn đặt tên CSS class cho mọi showcase. Tên class phải phản ánh UI Layer (elevation).

Referenced by: new-showcase.md (this file), post-change.md (step 7b)

Cú pháp

text
.[layer]-[component]__[element]--[modifier]
Phần Bắt buộc Mô tả
layer Có* ground-, card-, surface- (bỏ nếu item-level)
component Vai trò UI, KHÔNG phải business data
__element Tuỳ BEM child element
--modifier Tuỳ Variant / state

⚡ Elevation Token Contract (BẮT BUỘC)

Nguyên tắc gốc: Mỗi component phải được gán layer TRƯỚC khi viết CSS. Layer quyết định token → token quyết định giá trị → đổi value = scale toàn bộ.

3 Layers — Mỗi layer lock 4 thuộc tính

Layer Prefix background color border-color box-shadow
Ground ground- var(--background) hoặc var(--canvas) var(--foreground) var(--border) none
Card card- var(--card) var(--card-foreground) var(--border) var(--shadow-sm) hoặc none
Surface surface- var(--surface) var(--surface-foreground) var(--border) var(--shadow-lg) trở lên

Item-level (no prefix) — inherit từ parent layer

text
.btn, .badge, .avatar, .icon, .tab, .divider

Items không set bg/fg riêng (trừ variant colors như --primary). Chúng kế thừa từ container.

Liquid Glass — Ngoại lệ có kiểm soát

backdrop-filter và decorative animations (shimmer, orbs) được phép hardcode. Nhưng background, color, border-color PHẢI dùng token.

css
/* ✅ Liquid glass đúng cách */
.card-account__glass {
    background: var(--card);             /* ← token */
    backdrop-filter: blur(40px) saturate(160%);
    border: 1px solid var(--border);     /* ← token */
}

🆕 New Value Escalation — Khi palette không đủ

KHÔNG sửa DS gốc. Có 4 tầng xử lý — chọn tầng thấp nhất phù hợp.

text
Tầng 1 (Ưu tiên)    Dùng token có sẵn trong palette
     ↓ không có
Tầng 2               --local-* trong showcase CSS
     ↓ nhiều showcase cùng cần
Tầng 3               styles/*.json (style token)
     ↓ MỌI showcase cần
Tầng 4               Gap Report → primitives/shared (cần User approve)

Tầng 2: Local variable — --local-*

Token CHỈ dùng trong 1 showcase → khai báo ngay trong file CSS:

css
:root {
    /* ─── Local tokens (scope: showcase only) ─── */
    --local-nab-gold: #f5c400;
    --local-nab-gradient-hero: linear-gradient(135deg, 
        rgba(40, 140, 60, .18), rgba(220, 195, 50, .14));
}

Naming rule: --local-{showcase}-{name}

Tầng 3 → 4: Escalation

  • Tầng 3 (styles/*.json): ≥2 showcases cùng cần → promote. PHẢI ref primitives.
  • Tầng 4 (Gap Report): ≥3 showcases + tất cả styles cần → đề xuất. Cần User approve.

Bảo toàn DS gốc

Hành vi ✅ Cho phép ❌ TUYỆT ĐỐI KHÔNG
Thêm --local-* trong showcase CSS
Thêm effect vào styles/*.json ✅ (nếu đủ tiêu chí)
Sửa primitives/, modes/, shared/, themes/ ❌ Không có User approve
Hardcode rgba() cho bg/fg/border
Hardcode rgba() cho animation ✅ shimmer, orb, glow

Elevation Map — Deliverable bắt buộc

TRƯỚC khi viết CSS, agent phải output bảng Elevation Map (xem Step 4) → User phải approve TRƯỚC KHI code.

6 Rules

R1. Class prefix PHẢI phản ánh UI Layer

css
/* ✅ */ .card-account   { background: var(--card); }
/* ✅ */ .surface-nav    { background: var(--surface); }
/* ❌ */ .balance-card   { background: rgba(15, 15, 15, .7); }

R2. KHÔNG đặt tên theo business data

Tên = vai trò UI, không phải nội dung nghiệp vụ:

❌ Sai ✅ Đúng Lý do
.balance-card .card-account "balance" là data
.approval-card .card-task "approval" là domain
.vip-badge .badge--vip VIP là modifier

Ngoại lệ: Feature-specific names OK: .card-cashflow ✅, .card-services

R3. KHÔNG viết tắt (trừ .btn)

R4. BEM cho children

css
.card-account              /* Block */
.card-account__glass       /* Element */
.card-account--elevated    /* Modifier */

R5. Variant dùng modifier, KHÔNG tạo class mới

R6. State suffix chuẩn: --active, --disabled, --done, --visible, --loading, --open

Decision Tree

text
Component nào?
│
├─ Floating (z-index > 0, overlay)?  → surface-
├─ Panel / Card (elevated, border)?  → card-
├─ Page-level / Fixed bar?           → ground-
└─ Small inline element?             → no prefix (btn, badge, avatar)

Token Palette per Layer — Quick Ref

Chi tiết đầy đủ: Xem token-reviewer SKILL.md §1 + ATOMIC-MAPPING.md

Layer bg fg border shadow density tier
Ground --background, --canvas --foreground --border none --page-*
Card (on page) --card, --card-subtle --card-foreground --card-border --shadow-sm --section-*
Card (nested) --card, --card-subtle --card-foreground --card-border --shadow-sm --group-*
Surface --surface --surface-foreground --border --shadow-lg+ --section-*
Item --primary, --secondary …-foreground --comp-*

Tier assignment rule: Card directly on page → section tier. Card inside section → group tier. See knowledge/research/density-formula.md §Usage Rule for details.

Checklist — Code Review

text
☐ 1. Class prefix đúng layer?
☐ 2. Tên theo vai trò UI, KHÔNG theo business data?
☐ 3. Không viết tắt?
☐ 4. Children dùng BEM?
☐ 5. CSS body dùng đúng token cho layer?
☐ 6. State dùng suffix chuẩn?
☐ 7. Density tier tokens match nesting context (page/section/group/comp)?