Prisma

--- description: Hướng dẫn Agent tự động tạo UI Component Sidebar / Navigation Rail dựa trên Design Tokens, có ngữ nghĩa chuẩn Material 3 & iOS HIG

Sidebar Component Generation Skill

Skill này hướng dẫn bạn (AI Agent) tạo component Sidebar / Navigation Rail — thanh điều hướng dọc bên trái cho dashboard, admin, và complex apps.

1. Mục tiêu (Objective)

Tạo component Sidebar collapsible, hỗ trợ nested navigation, badges, và tích hợp 100% Design Tokens. Phải responsive: collapse thành Rail (icon-only) hoặc ẩn hoàn toàn trên mobile.

2. AI Context & Intent (Ngữ cảnh cho AI)

Khi nào dùng Sidebar?

  • Dashboard / Admin panel: Navigation chính cho complex apps
  • Multi-section apps: Email, project management, CRM
  • Khi có > 7 navigation items: navigation-menu không đủ chỗ

Phân biệt với component khác

Tình huống Component đúng Lý do
Navigation dọc, persistent Sidebar Luôn hiện, nhiều items
Navigation ngang, top navigation-menu Ít items, compact
Slide-in tạm thời Drawer Temporary, overlay
Settings categories Sidebar hoặc Tabs Tuỳ complexity

Decision Tree cho AI

text
Cần navigation panel?
├─ Permanent, vertical, nhiều items → Sidebar
│   ├─ Dashboard/admin → Sidebar (default)
│   ├─ Cần tiết kiệm space → Sidebar (collapsible)
│   └─ Mobile → Sidebar → Drawer (temporary overlay)
├─ Temporary overlay panel → Drawer
├─ Horizontal top → navigation-menu
└─ Content switching cùng page → Tabs

3. Ngữ nghĩa & Phân loại (Semantics)

3.1. States

State Width Mô tả
expanded 256px (default) Full sidebar: icon + text + badges
collapsed 64px Icon-only rail: hover tooltip cho labels
hidden 0px Ẩn hoàn toàn (mobile default)

3.2. Anatomy

text
┌──────────────────────┐
│  [Logo / Brand]      │
│                      │
│  SECTION LABEL       │
│  ● Dashboard         │ ← active (highlight bg + left indicator)
│  ○ Transactions      │
│  ○ Cards             │
│  ○ Reports       [5] │ ← badge counter
│                      │
│  SETTINGS            │
│  ○ Account           │
│  ○ Security          │
│    ├─ Password       │ ← nested sub-item
│    └─ 2FA            │
│                      │
│  ──────────────────  │ ← divider
│  ○ Help & Support    │
│  ○ Logout            │
└──────────────────────┘

3.3. Navigation Item Types

Type Mô tả
Link Điều hướng đến page
Parent Có sub-items, click → expand/collapse children
External Link external với icon ↗
Action Trigger action (logout, settings)

3.4. Slot Map (Figma ↔ Code)

📎 Source: slot-manifest.jsonsidebar · Layer: surface

Figma Slot data-slot CSS Class Required Accepts
Root sidebar .surface-sidebar
Header sidebar-header .slot-header brand-logo, user-profile
Content sidebar-content .slot-body nav-group, list
Footer sidebar-footer .slot-footer user-profile, settings-link, collapse-button

4. Token Mapping

?? Atomic Mapping: Xem ATOMIC-MAPPING.md ? m?c sidebar. Component token JSON files d� deprecated.

Semantic color tokens (qua Mode layer) và state-specific colors được define đầy đủ trong file .tokens.json.

5. Props & API

typescript
interface SidebarProps {
  /** Current state */
  state?: 'expanded' | 'collapsed' | 'hidden';
  /** Width preset */
  width?: 'compact' | 'default' | 'wide';
  /** Header/logo element */
  header?: ReactNode;
  /** Footer element (user info, logout) */
  footer?: ReactNode;
  /** On state change (collapse/expand) */
  onStateChange?: (state: 'expanded' | 'collapsed' | 'hidden') => void;
  /** Overlay mode on mobile (renders as Drawer) */
  mobileOverlay?: boolean;
  children: ReactNode;
}

interface SidebarSectionProps {
  /** Section label (uppercase) */
  label?: string;
  children: ReactNode;
}

interface SidebarItemProps {
  /** Label text */
  label: string;
  /** Icon (required for collapsed state) */
  icon: ReactNode;
  /** Navigation target */
  href?: string;
  onClick?: () => void;
  /** Active state */
  active?: boolean;
  /** Badge counter */
  badge?: string | number;
  /** Disabled */
  disabled?: boolean;
  /** Nested sub-items */
  children?: ReactNode;
}

6. Accessibility (a11y)

  • Semantic HTML: <nav> + aria-label="Sidebar navigation".
  • Collapse button: aria-label="Collapse sidebar" / "Expand sidebar", aria-expanded.
  • Active item: aria-current="page".
  • Nested: Parent item có aria-expanded, sub-items trong <ul>.
  • Keyboard: Tab qua items, Enter/Space navigate hoặc expand/collapse parent, Arrow Up/Down trong submenu.
  • Badge: aria-label descriptive ("Transactions, 5 new").
  • Collapsed tooltip: Tooltip cho icon-only items phải có role="tooltip".
  • Mobile: Khi render as overlay, cần focus trap + Escape close.

7. Best Practices & Rules

  • Collapse persistent: Lưu trạng thái expand/collapse vào localStorage.
  • Mobile: Auto-hide → render as Drawer overlay.
  • Active indicator: Dùng left border bar + background highlight — 2 cues rõ ràng.
  • Section labels: UPPERCASE, smaller font, muted color — visual separator.
  • Nested max depth: Tối đa 2 levels (parent → children). Sâu hơn → redesign IA.
  • Không Hardcode: Mọi giá trị từ Token.
  • Icon: Sidebar items BẮT BUỘC dùng Lucide icon từ assets/icons/. CẤM dùng text emoji hoặc icon từ library khác. Xem icon.md mục 10.
  • Scroll: Sidebar content nên scroll independently.
  • Transition: Collapse animation smooth, text fade out trước khi width shrinks.

8. Example Usage

jsx
{/* Dashboard sidebar */}
<Sidebar
  state={sidebarState}
  onStateChange={setSidebarState}
  header={<Logo collapsed={sidebarState === 'collapsed'} />}
  footer={
    <SidebarItem icon={<LogoutIcon />} label="Đăng xuất" onClick={logout} />
  }
>
  <SidebarSection label="Menu chính">
    <SidebarItem icon={<DashboardIcon />} label="Tổng quan" href="/" active />
    <SidebarItem icon={<WalletIcon />} label="Giao dịch" href="/transactions" badge={5} />
    <SidebarItem icon={<CardIcon />} label="Thẻ" href="/cards" />
    <SidebarItem icon={<ChartIcon />} label="Báo cáo" href="/reports" />
  </SidebarSection>

  <SidebarSection label="Cài đặt">
    <SidebarItem icon={<UserIcon />} label="Tài khoản" href="/account" />
    <SidebarItem icon={<ShieldIcon />} label="Bảo mật">
      <SidebarItem label="Mật khẩu" href="/security/password" />
      <SidebarItem label="Xác thực 2 bước" href="/security/2fa" />
    </SidebarItem>
  </SidebarSection>
</Sidebar>