This will permanently delete your account and all associated data. This action cannot be reversed.
You have unsaved changes. Are you sure you want to leave this page?
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
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
┌─────────────────────────────────┐
│ ◉ [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, shapecircle, modecontained) - 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
promptthườ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.json→dialog· 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 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-foregroundcho bg/fg. Icon variants dùng--{semantic}-mutedpairs. 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
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-labelledbytrỏ đến title,aria-describedbytrỏ đế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 buttonprompt: Focus vào input field
- Return focus: Khi close, trả focus về trigger element ban đầu.
- Escape: Nhấn
Escapeclose dialog (trừ khicloseOnEscape=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. Xemicon.mdmụ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ùngbtn-lg— Dialog nhỏ, btn-lg chiếm quá nhiều diện tích. Cancel và Confirm PHẢI cùng size. Xembutton.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:
UIAlertControllerlà 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
{/* 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}
/>