Prisma

Naming Convention — Quy Tắc Đặt Tên Toàn Hệ Thống

Dành cho: Developer, Designer Mục tiêu: Thống nhất cách đặt tên từ token → CSS class → Figma frame Thời gian đọc: ~15 phút


1. Tổng Quan — 1 Naming Convention, 5 Contexts

Prisma dùng 1 bộ quy tắc nhất quán cho tất cả:

Context Format Ví dụ
CSS Token --{tier}-{property}-{variant} --group-padding-default
CSS Class {layer}-{role}__{element}--{modifier} card-stat__value--positive
DS Component .{component}--{variant} .btn--primary, .input--error
Figma Frame {Layer} / {Component} / {Variant} Card / Stat / Default
Figma Sub-frame _{element} hoặc {slot} _icon, _value, header

2. CSS Token Naming

Format

text
--{tier}-{property}-{variant}

Tier (4 cấp)

Tier Prefix Dùng cho
Page --page- Background, main content area
Section --section- Content regions, groups of cards
Group --group- Cards, panels, visual containers
Comp --comp- Buttons, inputs, leaf elements

Property Types

Property Dạng token Ví dụ
Padding {tier}-padding-{size} --group-padding-default
Stack gap {tier}-stack-gap-{size} --section-stack-gap-large
Inline gap {tier}-inline-gap-{size} --comp-inline-gap-default
Grid gap {tier}-grid-{direction}-gap --section-grid-row-gap
Radius {tier}-radius-{variant} --group-radius-default
Margin {tier}-margin-{size} --page-margin-default
Height {tier}-height-{size} --comp-height-default

Size Variants

text
xlarge > large > default > small > xsmall

Rule: Luôn dùng default trước. Chỉ dùng large/small khi cần size khác biệt rõ ràng.

Ví Dụ Đầy Đủ: Stat Card

css
.card-stat {
  /* ✅ Tier tokens — group level */
  padding: var(--group-padding-default);       /* --group-padding-default */
  gap: var(--group-stack-gap-default);          /* --group-stack-gap-default */
  border-radius: var(--group-radius-default);   /* --group-radius-default */

  /* ✅ Color tokens — card layer */
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--card-border);
}

3. CSS Class Naming (Elevation BEM)

Format

text
.[layer]-[role]__[element]--[modifier]
Part Bắt buộc? Ý nghĩa Ví dụ
layer Elevation layer: ground, card, surface card-
role UI role (semantic) -stat, -nav, -form
__element Child element bên trong __value, __icon, __label
--modifier Trạng thái hoặc variant --active, --positive, --compact

Quy tắc đặt tên role

✅ Đúng (UI role) ❌ Sai (business data)
card-stat balance-card
card-product loan-card
card-form registration-card
surface-nav menu-bar
ground-content main-area

Ví Dụ Đầy Đủ: Dashboard Stat Card

text
card-stat                      → Component root (group tier)
├── card-stat__header          → Header area
│   ├── card-stat__label       → "Revenue" text
│   └── card-stat__icon        → Trend icon
├── card-stat__value           → "$12,450" main number
│   └── card-stat__value--positive → Green variant
└── card-stat__trend           → "+12% from last month"
html
<article class="card-stat">
  <div class="card-stat__header">
    <span class="card-stat__label">Revenue</span>
    <i class="card-stat__icon" data-lucide="trending-up"></i>
  </div>
  <span class="card-stat__value card-stat__value--positive">$12,450</span>
  <span class="card-stat__trend">+12% from last month</span>
</article>
css
.card-stat { ... }
.card-stat__header { display: flex; justify-content: space-between; align-items: center; }
.card-stat__label { font: var(--text-style-label-default-font-weight) var(--text-style-label-default-font-size)/var(--text-style-label-default-line-height) inherit; }
.card-stat__value { font: var(--text-style-heading-2-font-weight) var(--text-style-heading-2-font-size)/var(--text-style-heading-2-line-height) inherit; }
.card-stat__value--positive { color: var(--success); }
.card-stat__value--negative { color: var(--destructive); }
.card-stat__trend { font: var(--text-style-caption-font-weight) var(--text-style-caption-font-size)/var(--text-style-caption-line-height) inherit; color: var(--muted-foreground); }

4. DS Component Naming (Shared Components)

DS components (.btn, .input, .badge, v.v.) KHÔNG dùng layer prefix — chúng là layer-agnostic.

Format

text
.{component}--{variant}

Ví dụ

Component Variant Class
Button primary .btn--primary
Button secondary .btn--secondary
Button ghost .btn--ghost
Input error .input--error
Badge success .badge--success
Card elevated .card-elevated
Tabs segment .tabs--segment

Sub-component (BEM Element)

text
.{component}__{element}
Component Sub-element Class
Tab icon .tab__icon
Card header .card-header
Card body .card-body
Card footer .card-footer
Card title .card-title
Alert icon .alert__icon
Alert content .alert__content

Note: DS card component dùng - thay vì __ do legacy convention (.card-header thay vì .card__header). Showcase card classes dùng __ (.card-stat__header).


5. Page-Level Naming — Từ Page đến Comp

Ví Dụ Đầy Đủ: Finance Dashboard

text
LEVEL 0 — PAGE
ground-app                              → Body / root container
├── surface-topbar                      → Top navigation bar
│   ├── surface-topbar__brand           → Logo + app name
│   ├── surface-topbar__search          → Search input
│   └── surface-topbar__actions         → User avatar, notifications
│
├── surface-sidebar                     → Left sidebar
│   ├── surface-sidebar__nav            → Navigation links
│   └── surface-sidebar__footer         → Collapse toggle
│
└── ground-content                      → Main scrollable area

    LEVEL 1 — SECTION
    ├── ground-content__overview        → Stats section
    │
    │   LEVEL 2 — GROUP
    │   ├── card-stat                   → Revenue card
    │   │   ├── card-stat__label        → "Revenue"
    │   │   ├── card-stat__value        → "$12,450"
    │   │   └── card-stat__trend        → "+12%"
    │   │
    │   ├── card-stat                   → Users card
    │   ├── card-stat                   → Orders card
    │   └── card-stat                   → Growth card
    │
    ├── ground-content__analytics       → Chart section
    │   └── card-chart                  → Chart container
    │       ├── card-chart__header      → Title + filter buttons
    │       │
    │       │   LEVEL 3 — COMP (no prefix)
    │       │   ├── btn--ghost          → "Weekly" toggle
    │       │   ├── btn--ghost          → "Monthly" toggle
    │       │   └── btn--primary        → "Yearly" toggle
    │       │
    │       └── card-chart__canvas      → Chart canvas area
    │
    └── ground-content__transactions    → Table section
        └── card-table                  → Table container (slotted)
            ├── .slot-header            → Title + "Export" button
            ├── .slot-body-flush        → <table> full-width
            └── .slot-footer-between    → Pagination

CSS tương ứng

css
/* LEVEL 0 — Page */
.ground-app {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr;
  min-height: 100vh;
  background: var(--canvas);
}

.ground-content {
  padding: var(--page-padding-default);
  display: flex;
  flex-direction: column;
  gap: var(--page-stack-gap-default);
  overflow-y: auto;
}

/* LEVEL 1 — Section */
.ground-content__overview {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--section-grid-row-gap) var(--section-grid-column-gap);
}

.ground-content__analytics,
.ground-content__transactions {
  display: flex;
  flex-direction: column;
  gap: var(--section-stack-gap-default);
}

/* LEVEL 2 — Group */
.card-stat {
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--card-border);
  border-radius: var(--group-radius-default);
  padding: var(--group-padding-default);
  display: flex;
  flex-direction: column;
  gap: var(--group-stack-gap-small);
}

/* LEVEL 3 — Comp (NO layer prefix) */
.card-stat__value {
  font-size: var(--text-style-heading-2-font-size);
  font-weight: var(--text-style-heading-2-font-weight);
}

6. Figma Frame Naming

Frame Hierarchy

Figma frames mirror CSS naming nhưng dùng / separator thay vì - / __:

text
Page / Section / Component / Variant / State

Ví dụ

Figma Frame Name CSS Class
Card / Stat / Default .card-stat
Card / Stat / Default / Hover .card-stat:hover
Card / Chart / With Filter .card-chart.card-chart--filtered
Surface / Topbar / Default .surface-topbar
Surface / Sidebar / Collapsed .surface-sidebar--collapsed
Ground / Content / Overview .ground-content__overview

Sub-frame Naming

Figma sub-frames (auto-layout children) dùng prefix _ để phân biệt structural frame vs semantic element:

Sub-frame Ý nghĩa CSS
_header Structural container .card-stat__header
_body Content area .card-stat__body
_footer Footer area .card-stat__footer
_icon Icon slot .card-stat__icon
_actions Button group .card-stat__actions
Label Text content (no _) .card-stat__label
Value Text content (no _) .card-stat__value

Figma Component Variants

text
Component Name: Card / Stat
Properties:
├── Size: sm | md | lg
├── State: default | hover | active | disabled
├── Trend: positive | negative | neutral
└── Has Icon: true | false

Rule: Sub-frames bắt đầu bằng _ → structural (frame/layout). Text/icon nodes KHÔNG có _ → content elements.


7. Mapping Table — CSS ↔ Figma ↔ Token

Level CSS Class Figma Frame Token Tier
Page .ground-app Ground / App --page-*
Section .ground-content__overview Ground / Content / Overview --section-*
Group .card-stat Card / Stat / Default --group-*
Sub-element .card-stat__value Value (text node) --comp-*
Modifier .card-stat__value--positive Property: Trend = positive (conditional)
DS Component .btn--primary Button / Primary / Default --comp-*

8. Anti-Patterns

❌ Tên theo business data

css
/* ❌ SAI */
.balance-display { ... }
.loan-interest-rate { ... }
.customer-profile-card { ... }

/* ✅ ĐÚNG */
.card-stat__value { ... }
.card-detail__rate { ... }
.card-profile { ... }

❌ Thiếu layer prefix

css
/* ❌ SAI — không biết element thuộc layer nào */
.dashboard-header { ... }
.stats-container { ... }

/* ✅ ĐÚNG */
.surface-topbar { ... }
.ground-content__overview { ... }

❌ Quá nhiều nesting levels

css
/* ❌ SAI — quá sâu, khó maintain */
.card-stat__header__icon__wrapper { ... }

/* ✅ ĐÚNG — flatten, tối đa 1 level `__` */
.card-stat__icon { ... }

❌ Figma frame không match CSS

text
/* ❌ SAI */
Figma: "Stats Card"     →  CSS: .card-stat
Figma: "stat_card_v2"   →  CSS: .card-stat

/* ✅ ĐÚNG — đồng bộ */
Figma: "Card / Stat"    →  CSS: .card-stat

9. Quick Reference — Naming Cheat Sheet

text
TOKEN:  --{tier}-{property}-{variant}
        --group-padding-default
        --section-stack-gap-large
        --comp-radius-capsule

CLASS:  {layer}-{role}__{element}--{modifier}
        card-stat
        card-stat__value
        card-stat__value--positive
        surface-topbar__actions

COMP:   {component}--{variant}
        btn--primary
        input--error
        badge--success

FIGMA:  {Layer} / {Component} / {Variant}
        Card / Stat / Default
        Surface / Topbar / Default
        Button / Primary / Hover

SUB:    _{structural}  |  {Content}
        _header        |  Label
        _body          |  Value
        _actions       |  Icon

Quy tắc vàng: Nếu bạn không thể đọc tên class và biết ngay nó thuộc layer nào + làm gì → tên chưa đủ tốt.