Live Preview
Skeleton Component Generation Skill
Skill này hướng dẫn bạn (AI Agent) tạo component Skeleton — placeholder loading hiển thị trước khi nội dung thật tải xong.
1. Mục tiêu (Objective)
Tạo component Skeleton với shimmer animation, hỗ trợ nhiều hình dạng (text, circle, rectangle), có thể compose thành loading layout. Tích hợp 100% Design Tokens.
2. AI Context & Intent (Ngữ cảnh cho AI)
Khi nào dùng Skeleton?
- Content đang tải: Thay thế text, image, card khi fetch data
- Perceived performance: Giảm cảm giác chờ đợi (tốt hơn spinner)
- Layout preservation: Giữ layout ổn định, tránh content shift
Phân biệt với component khác
| Tình huống | Component đúng | Lý do |
|---|---|---|
| Nội dung đang tải, biết layout | Skeleton | Giữ đúng layout shape |
| Đang tải, không biết layout | Spinner / Loading | Không giả lập layout |
| Action đang xử lý (submit) | Spinner trong Button | User triggered action |
| Page transition | Progress Bar | Navigation loading |
| Empty state (không có data) | Empty State component | Không phải loading |
Decision Tree cho AI
text
Content đang tải?
├─ Biết layout sẽ như nào → Skeleton (mimic layout)
│ ├─ Text line → Skeleton variant="text"
│ ├─ Avatar circle → Skeleton variant="circle"
│ ├─ Image rect → Skeleton variant="rectangle"
│ └─ Card phức tạp → Compose nhiều Skeleton
├─ Không biết layout → Spinner / Loading indicator
├─ User vừa submit → Button loading state
└─ Không có data → Empty State
3. Ngữ nghĩa & Phân loại (Semantics)
3.1. Variants
| Variant | Hình dạng | Use case |
|---|---|---|
text |
Rectangle, height = line-height | Text placeholder |
circle |
Circle | Avatar, icon placeholder |
rectangle |
Rectangle, custom w×h | Image, card, banner |
rounded |
Rectangle + border-radius | Button, input placeholder |
3.2. Animation
- Shimmer/Pulse: Gradient animation di chuyển từ trái → phải (shimmer) hoặc fade in/out (pulse).
- Mặc định: shimmer. Cho phải disable animation (accessibility:
prefers-reduced-motion).
3.4. Slot Map (Figma ↔ Code)
📎 Source:
slot-manifest.json→skeleton· Layer: item
| Figma Slot | data-slot |
CSS Class | Required | Accepts |
|---|---|---|---|---|
| Root | skeleton |
.skeleton |
✅ | — |
| Line | skeleton-line |
— | ❌ (n×) | — |
| Circle | skeleton-circle |
— | ❌ | — |
| Rect | skeleton-rect |
— | ❌ | — |
4. Token Mapping
📦 Token values: Xem
ATOMIC-MAPPING.md— single source of truth cho tất cả actual token values.
| Token | Type | Value | Mô tả |
|---|---|---|---|
radius-text |
number | {border-radius.default} |
Text lines radius |
radius-rounded |
number | {item.radius} |
Button/input placeholder radius |
radius-circle |
number | {border-radius.full} |
Avatar placeholder radius |
text-height.sm |
number | {font.leading.4} |
Small text line height |
text-height.md |
number | {font.leading.5} |
Default text line height |
text-height.lg |
number | {font.leading.7} |
Heading placeholder height |
gap |
number | {spacing.2} |
Gap between skeleton lines |
color.background |
color | {base.muted} |
Skeleton base color |
color.highlight |
color | {base.background} |
Shimmer bright point |
animation-duration |
number | 1500 |
Shimmer cycle duration (ms) |
transition |
string | {duration.fast-2} {easing.standard} |
Default interaction transition |
padding |
number | {item.padding-default} |
Internal padding |
5. Props & API
typescript
interface SkeletonProps {
/** Shape variant */
variant?: 'text' | 'circle' | 'rectangle' | 'rounded';
/** Width — number (px) hoặc string ("100%") */
width?: number | string;
/** Height — number (px) hoặc string */
height?: number | string;
/** Animation type */
animation?: 'shimmer' | 'pulse' | 'none';
/** Number of lines (variant="text") */
lines?: number;
/** Last line width (variant="text", lines > 1) */
lastLineWidth?: string; // vd: "60%" — dòng cuối ngắn hơn
}
6. Accessibility (a11y)
- ARIA:
role="status"+aria-label="Loading"hoặcaria-busy="true"trên container. - Reduced motion: Respect
prefers-reduced-motion: reduce— tắt shimmer animation, chỉ hiện static background. - Screen reader: Announce "Loading" khi skeleton visible, "Loaded" khi content replace skeleton.
7. Best Practices & Rules
- Mimic real layout: Skeleton phải giống layout thật nhất có thể — đúng số dòng, đúng kích thước.
- Không quá chi tiết: Không cần skeleton cho mỗi icon nhỏ — focus vào khối chính (text, image, card).
- Transition: Khi content load xong, fade in content — không snap.
- Không Hardcode: Mọi giá trị từ Token.
8. Example Usage
jsx
{/* Text placeholder */}
<Skeleton variant="text" lines={3} lastLineWidth="60%" />
{/* Avatar + text */}
<div style={{ display: 'flex', gap: 12 }}>
<Skeleton variant="circle" width={40} height={40} />
<div>
<Skeleton variant="text" width={120} />
<Skeleton variant="text" width={200} />
</div>
</div>
{/* Card skeleton */}
<Skeleton variant="rectangle" width="100%" height={200} />
<Skeleton variant="text" lines={2} />
<Skeleton variant="rounded" width={100} height={36} />