Prisma
Live Preview
Delete Account

This will permanently delete your account and all associated data. This action cannot be reversed.

Discard Changes?

You have unsaved changes. Are you sure you want to leave this page?

Location Access

This app needs access to your location to show nearby results. You can change this later in settings.

Dialog Component Generation Skill

Skill này hướng dẫn bạn (AI Agent) tạo component Dialog — overlay nhẹ dùng cho phản hồi của hệ thống: xác nhận hành động, thông báo lỗi, prompt nhập liệu đơn giản.

1. Mục tiêu (Objective)

Tạo component Dialog hoàn chỉnh cho các tình huống system feedback: confirm/cancel, alert message, simple prompt.

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

Khi nào dùng Dialog?

  • Xác nhận hành động nguy hiểm: "Bạn có chắc muốn xoá tài khoản?"
  • Thông báo kết quả hệ thống: "Giao dịch thành công!", "Thanh toán thất bại"
  • Prompt đơn giản: "Nhập lý do huỷ", "Đặt tên cho mục mới"
  • Permission request: "Cho phép truy cập vị trí?"

Đặc điểm cốt lõi

  • Bản chất: System feedback — cảnh báo, xác nhận từ hệ thống
  • Content: Title + description + tối đa 2 action buttons
  • Scroll: ❌ KHÔNG BAO GIỜ scroll
  • Size: Nhỏ gọn (320-448px)
  • Backdrop: ✅ Click dismiss (trừ variant confirm)

Decision Tree cho AI

text
Cần system feedback overlay?
├─ Confirm hành động → Dialog (confirm)
├─ Thông báo kết quả (success/error) → Dialog (alert) 
├─ Nhập giá trị đơn giản (1 field) → Dialog (prompt)
└─ Permission / consent → Dialog (confirm)

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

3.1. Variants

Variant Mô tả Icon (Lucide) Khi nào dùng
confirm Yes/No confirmation triangle-alert (triangle-alert.svg) Xác nhận hành động destructive
alert System notification info / circle-check / circle-x Thông báo kết quả (success/error/info)
prompt Input a single value Không có icon Nhập tên, lý do, giá trị

3.2. Severity (cho variant alert)

Severity Icon (Lucide) Mục đích
info info (info.svg) Thông tin trung lập
success circle-check (circle-check.svg) Hành động thành công
warning triangle-alert (triangle-alert.svg) Cảnh báo, cần chú ý
destructive circle-x (circle-x.svg) Lỗi, thất bại

3.3. Sizes

Size Max width Use case
sm 320px Simple confirm (1 line title)
md 384px Confirm with description, alert
lg 448px Prompt with input, detailed alert

3.4. Anatomy

text
┌─────────────────────────────────┐
│  ◉ [Lead Icon]                  │  ← Optional. Dùng lead-icon component
│                                 │     (circle, semantic muted bg)
│  Title                          │  ← Required. Ngắn gọn, rõ ràng
│  Description text here...       │  ← Optional. 1-2 câu giải thích
│                                 │
│  [Input field]                  │  ← Only for variant=prompt
│                                 │
│           [Cancel]  [Confirm]   │  ← Action buttons, trailing (web)
└─────────────────────────────────┘

Lead Icon rules:

  • Dùng lead-icon component (size lg = 40px, shape circle, mode contained)
  • Background: --{severity}-muted (ví dụ: --destructive-muted, --info-muted)
  • Color: --{severity} (ví dụ: --destructive, --info)
  • Optional: Dialog không bắt buộc có icon. Variant prompt thường KHÔNG có icon.
  • Vị trí: Trên title, căn trái (web) hoặc căn giữa (mobile)

3.5. Slot Map (Figma ↔ Code)

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

Figma Slot data-slot CSS Class Required Accepts
Root dialog .surface-dialog
Icon dialog-icon severity-icon (info, success, warning, destructive)
Content dialog-content .slot-body text-only, text+input (prompt)
Title dialog-title text
Description dialog-description text
Actions dialog-actions .slot-footer button-group (max 3)
html
<!-- HTML skeleton with data-slot -->
<div class="surface-dialog" data-slot="dialog" role="alertdialog" aria-modal="true">
  <div class="ds-leadicon ds-leadicon--lg" data-slot="dialog-icon">⚠</div>
  <div class="slot-body" data-slot="dialog-content">
    <h2 data-slot="dialog-title">Confirm?</h2>
    <p data-slot="dialog-description">This action cannot be undone.</p>
  </div>
  <div class="slot-footer" data-slot="dialog-actions">
    <button class="btn btn--outline">Cancel</button>
    <button class="btn btn--destructive">Delete</button>
  </div>
</div>

4. Token Mapping

📦 Atomic Mapping: Xem ATOMIC-MAPPING.md → mục dialog — UI Layer: Surface, Density Tier: section.

Dialog dùng trực tiếp --surface / --surface-foreground cho bg/fg. Icon variants dùng --{semantic}-muted pairs. Component token JSON files đã deprecated.

Token Type Value Mô tả
title.font-size number {font.size.lg} Dialog title — heading-4 (18px)
title.font-weight number {font.weight.semibold} Dialog title weight (600)
description.font-size number {font.size.sm} Description text (14px)
description.font-weight number {font.weight.normal} Description weight (400)
color.surface color {base.surface} Dialog background
color.surface-foreground color {base.surface-foreground} Dialog text color
color.title color {base.foreground} Title text color
color.description color {base.muted-foreground} Description text color
radius number {module.radius-large} Corner radius
padding number {module.padding-default} Internal padding
elevation shadow {elevation.level-4} Shadow elevation
z-index number {z-index.modal} Stacking order
color.backdrop color {base.background-overlay} Semi-transparent backdrop

5. Props & API

typescript
interface DialogProps {
  /** Mở/đóng */
  open: boolean;
  /** Callback khi close */
  onClose: () => void;
  /** Variant */
  variant?: 'confirm' | 'alert' | 'prompt';
  /** Severity (chỉ cho variant=alert) */
  severity?: 'info' | 'success' | 'warning' | 'destructive';
  /** Size */
  size?: 'sm' | 'md' | 'lg';
  /** Title — bắt buộc */
  title: string;
  /** Description */
  description?: string;
  /** Confirm button text */
  confirmText?: string; // default: "Xác nhận"
  /** Cancel button text */
  cancelText?: string; // default: "Huỷ"
  /** Confirm button variant (liên kết với button component) */
  confirmVariant?: 'primary' | 'destructive';
  /** Callback khi confirm */
  onConfirm?: () => void;
  /** Close on backdrop click — false cho confirm variant */
  closeOnBackdrop?: boolean;
  /** Close on Escape key */
  closeOnEscape?: boolean; // default: true
}

interface DialogPromptProps extends DialogProps {
  variant: 'prompt';
  /** Input label */
  inputLabel?: string;
  /** Input placeholder */
  inputPlaceholder?: string;
  /** Input default value */
  inputDefaultValue?: string;
  /** Callback với input value khi confirm */
  onConfirm: (value: string) => void;
}

6. Accessibility (a11y)

  • Role: role="alertdialog" cho confirm/alert. role="dialog" cho prompt.
  • Label: aria-labelledby trỏ đến title, aria-describedby trỏ đến description.
  • Focus trap: Focus PHẢI bị trap bên trong dialog — Tab cycle qua buttons/input.
  • Initial focus:
    • confirm: Focus vào Cancel button (tránh confirm nhầm)
    • alert: Focus vào primary action button
    • prompt: Focus vào input field
  • Return focus: Khi close, trả focus về trigger element ban đầu.
  • Escape: Nhấn Escape close dialog (trừ khi closeOnEscape=false).
  • Auto-announce: Content được announce bởi screen reader khi dialog mở.

7. Best Practices & Rules

  • Ngắn gọn: Title ≤ 1 dòng, description ≤ 2 câu.
  • KHÔNG scroll: Dialog body KHÔNG bao giờ scroll.
  • Max 2 actions: Confirm + Cancel. Không nhiều hơn.
  • Confirm variant: Backdrop click KHÔNG close (buộc user chọn action).
  • Destructive confirm: Dùng confirmVariant="destructive" + icon warning cho hành động xoá/huỷ.
  • Icon: CHỈ dùng Lucide icon từ assets/icons/. CẤM dùng text emoji. Xem icon.md mục 10.
  • Không Hardcode: Mọi giá trị từ Token.
  • Không nested: KHÔNG mở Dialog từ trong Dialog.
  • Button size (BS-3, BS-5): Action buttons trong Dialog PHẢI dùng md (default). KHÔNG dùng btn-lg — Dialog nhỏ, btn-lg chiếm quá nhiều diện tích. Cancel và Confirm PHẢI cùng size. Xem button.md §4.7.

8. Platform Mapping

Property Web (HTML) iOS (UIKit/SwiftUI) Android (M3)
Confirm dialog <dialog> + role="alertdialog" UIAlertController(.alert) AlertDialog (M3)
Alert dialog <dialog> + role="alertdialog" UIAlertController(.alert) AlertDialog (M3)
Prompt dialog <dialog> + role="dialog" UIAlertController + .addTextField AlertDialog + TextField
Backdrop dismiss Click handler preferredAction setCancelable()
Animation CSS transform: scale() + opacity UIKit spring M3 ElevationOverlay

Platform-specific Notes

  • iOS: UIAlertController là chuẩn — KHÔNG custom design confirmation dialogs trên iOS
  • Android (M3): AlertDialog → dùng M3 theme tokens, rounded corners 28dp
  • Web: Native <dialog> element khi có thể, polyfill cho browser cũ

9. Example Usage

jsx
{/* Confirm delete */}
<Dialog
  open={isOpen}
  onClose={close}
  variant="confirm"
  severity="destructive"
  title="Xoá giao dịch?"
  description="Hành động này không thể hoàn tác. Giao dịch #VNP12345 sẽ bị xoá vĩnh viễn."
  confirmText="Xoá"
  confirmVariant="destructive"
  onConfirm={handleDelete}
/>

{/* Success alert */}
<Dialog
  open={isOpen}
  onClose={close}
  variant="alert"
  severity="success"
  title="Giao dịch thành công!"
  description="Số tiền 500,000₫ đã được chuyển đến tài khoản người nhận."
  confirmText="Đóng"
/>

{/* Error alert */}
<Dialog
  open={isOpen}
  onClose={close}
  variant="alert"
  severity="destructive"
  title="Thanh toán thất bại"
  description="Không thể kết nối đến ngân hàng. Vui lòng thử lại sau."
  confirmText="Thử lại"
  cancelText="Huỷ"
  onConfirm={retry}
/>

{/* Prompt input */}
<Dialog
  open={isOpen}
  onClose={close}
  variant="prompt"
  title="Nhập lý do huỷ"
  description="Vui lòng cho chúng tôi biết lý do huỷ giao dịch."
  inputPlaceholder="Nhập lý do..."
  confirmText="Gửi"
  onConfirm={(value) => handleCancel(value)}
/>

{/* Permission request */}
<Dialog
  open={isOpen}
  onClose={close}
  variant="confirm"
  severity="info"
  title="Cho phép truy cập vị trí?"
  description="Ứng dụng cần truy cập vị trí để tìm ATM gần nhất."
  confirmText="Cho phép"
  cancelText="Từ chối"
  onConfirm={requestLocation}
/>