Live Preview
Uploading...65%
Complete100%
Loading...30%
Progress Bar Component
Skill này hướng dẫn tạo component Progress Bar — hiển thị tiến trình determinate/indeterminate cho upload, loading, step completion.
1. Mục tiêu (Objective)
Tạo component Progress Bar cho hiển thị determinate/indeterminate progress: upload, loading, step completion. Hỗ trợ nhiều sizes, variants, và types.
2. AI Context & Intent (Ngữ cảnh cho AI)
Khi nào dùng Progress Bar?
- File upload: Show upload progress 0-100%
- Step completion: 3/5 steps done → 60%
- Loading content: Indeterminate while fetching data
- Form validation: Password strength meter
⚠️ Phân biệt Progress Bar vs Spinner vs Skeleton (QUAN TRỌNG)
| Tiêu chí | Progress Bar | Spinner | Skeleton |
|---|---|---|---|
| Bản chất | Linear bar | Circular animation | Content placeholder |
| Best for | Known progress (%) | Unknown duration | Known layout, loading |
| Info shown | Exact percentage | Just "loading" | Visual content preview |
| Shape | Horizontal bar | Circle | Mimics content |
| Ví dụ | File upload (45%) | Button loading | Page skeleton |
Decision Tree cho AI
text
Cần show loading state?
├─ Biết progress % chính xác → Progress Bar (determinate)
│ ├─ Upload/download → Progress Bar + label (%)
│ ├─ Step completion → Progress Bar + "3 of 5"
│ └─ Dual progress → Progress Bar (buffer type)
│
├─ Không biết duration → chọn theo context:
│ ├─ Biết content layout → Skeleton
│ ├─ Inline nhỏ → Spinner (xs/sm)
│ ├─ Button loading → Spinner (button variant)
│ ├─ Section loading → Progress Bar (indeterminate)
│ └─ Page loading → Spinner (xl) hoặc Skeleton
│
└─ Process status theo steps → Stepper
3. Anatomy
text
Determinate:
Uploading... 45%
┌──────────────────────────────┐
│████████████░░░░░░░░░░░░░░░░░│ ← Track: --muted bg
└──────────────────────────────┘ Fill: --primary bg
Radius: --radius-full
Buffer (YouTube-style):
Buffering...
┌──────────────────────────────┐
│████████▓▓▓▓▓░░░░░░░░░░░░░░░│ ← Fill ████ + Buffer ▓▓▓
└──────────────────────────────┘
Indeterminate:
Loading...
┌──────────────────────────────┐
│░░░░████████░░░░░░░░░░░░░░░░░│ ← Animated sliding fill
└──────────────────────────────┘
4. Platform Mapping
| Platform | Component | Key Difference |
|---|---|---|
| Web | <progress> / ProgressBar |
Linear horizontal bar |
| iOS | UIProgressView | Thin linear bar, tinting |
| Android (M3) | LinearProgressIndicator | Determinate + indeterminate |
| Fluent | ProgressBar | Linear with label |
| Carbon | ProgressBar | With percentage label |
Cross-platform: ALL platforms, consistent UX.
5. Variants
| Variant | Mô tả |
|---|---|
default |
Primary color fill |
success |
Green fill — completed |
warning |
Yellow fill — attention needed |
error |
Red fill — failed/blocked |
Types
| Type | Mô tả |
|---|---|
determinate |
Known progress 0–100% |
indeterminate |
Unknown duration, animation loop |
buffer |
YouTube-style: loaded + played |
Sizes
sm (2px), md (4px), lg (8px)
5.4. Slot Map (Figma ↔ Code)
📎 Source:
slot-manifest.json→progress· Layer: item
| Figma Slot | data-slot |
CSS Class | Required | Accepts |
|---|---|---|---|---|
| Root | progress |
.progress-bar |
✅ | — |
| Track | progress-track |
— | ✅ | — |
| Fill | progress-fill |
.progress-fill |
✅ | — |
| Label | progress-label |
— | ❌ | text, percentage |
6. Token Mapping
📦 Atomic Mapping: Xem
ATOMIC-MAPPING.md→ mục progress — Density Tier: comp.Track bg dùng
--muted, fill bg dùng--primary(default), radius dùng--radius-full. Variants dùng--warning,--success. Component token JSON files đã deprecated.
7. Props & API
typescript
interface ProgressBarProps {
value?: number; // 0–100, undefined = indeterminate
variant?: 'default' | 'success' | 'warning' | 'error';
size?: 'sm' | 'md' | 'lg';
showLabel?: boolean; // Show percentage text
bufferValue?: number; // Buffer progress (0–100)
'aria-label': string;
}
8. Accessibility (a11y)
role="progressbar",aria-valuenow,aria-valuemin="0",aria-valuemax="100".- Indeterminate: omit
aria-valuenow. aria-labelrequired (e.g., "Uploading file").
9. Best Practices & Rules
- Animation: Smooth
widthtransition for determinate, CSS animation for indeterminate. - Stripe animation: Optional animated stripes for active progress.
- Label position: Inside bar when
lg, above/below whensm/md. - Không Hardcode: Mọi giá trị từ Token.
10. Example Usage
jsx
{/* File upload progress */}
<ProgressBar
value={uploadPercent}
showLabel
aria-label="Uploading document"
/>
{/* Step completion */}
<ProgressBar
value={(completedSteps / totalSteps) * 100}
variant="success"
size="lg"
aria-label="Onboarding progress"
/>
{/* Indeterminate loading */}
<ProgressBar
variant="default"
size="sm"
aria-label="Loading content"
/>
{/* Buffer (streaming) */}
<ProgressBar
value={playedPercent}
bufferValue={loadedPercent}
size="sm"
aria-label="Video progress"
/>