Skeleton
Mẫu chuẩnÔ giữ chỗ cho nội dung đã biết hình dạng trong lúc chờ dữ liệu, quét ngang liên tục.
Playground
Đổi brand, theme và hình dạng minh hoạ. "Hình dạng" ở đây không phải một prop của primitive — đó là bốn cách người gọi tự đặt className/style lên Skeleton. Primitive không có prop shape.
Vệt quét chạy liên tục, không có trạng thái tắt. Bật "giảm chuyển động" trong devtools để thấy nó chậm lại chứ không đứng hình.
import { Skeleton } from "@nexobox/ui";
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-2/3" />
</div>Khi nào sử dụng
Nên dùng
Giữ chỗ cho nội dung đã biết hình dạng trong lúc chờ dữ liệu về: một hàng trong danh sách, một thẻ, một đoạn văn. Giữ bố cục ổn định để trang không nhảy khi dữ liệu thật thay vào.
Tránh dùng
Một thao tác đang chạy mà người dùng vừa bấm — đó là trạng thái loading của Button. Nội dung chưa biết hình dạng — một skeleton đoán sai hình dạng còn tệ hơn một dòng chữ "đang tải". Một khoảng chờ dưới khoảng 300ms — skeleton chớp lên rồi biến mất gây nhiễu hơn là không hiện gì.
Anatomy
| # | Phần | Ghi chú |
|---|---|---|
| 1 | Root | <div aria-hidden="true"> duy nhất mà người dùng thấy và định hình. Nền --nf-semantic-surface-subtle, bo --nf-foundation-radius-small. |
Bên trong Root có một lớp quét tuyệt đối để chạy animation, bị overflow: hidden của Root cắt gọn — đây là chi tiết dựng hình của phần Root, không phải một phần thứ hai mà người dùng đặt tên, style hay tắt riêng.
Variants & states
Không có variant, không có size, không có preset dòng chữ, không có preset hình tròn. Bốn hình dạng dưới đây chỉ là className khác nhau trên cùng một primitive.
<Skeleton className="h-4 w-48" />
<div className="flex flex-col gap-2"> <Skeleton className="h-4 w-full" /> <Skeleton className="h-4 w-full" /> <Skeleton className="h-4 w-2/3" /> </div>
<Skeleton className="h-32 w-64" />
<Skeleton className="h-12 w-12 rounded-full" />
Chỉ một trạng thái, và nó là trạng thái chờ. hover, focus, disabled, error, empty: không có — primitive không nhận tương tác và không đại diện cho dữ liệu.
Design tokens
Root đọc --nf-semantic-surface-subtle và --nf-foundation-radius-small. Vệt quét chạy bằng keyframe nf-shimmer đã có sẵn — một phép tịnh tiến ngang, không đổi độ sáng, nên không tính là chớp theo A14. Nó dùng thời lượng --nf-component-skeleton-shimmer-duration, easing --nf-foundation-motion-easing-standard, và dải sáng của nó trộn từ --nf-semantic-surface-raised qua color-mix(in srgb, …, transparent). Dưới prefers-reduced-motion: reduce, token này đổi sang --nf-component-skeleton-shimmer-duration-reduced (1400ms → 2800ms) — vệt quét chậm lại, không đứng hình, theo DS-014 clause 18. Luật này sống ở tầng token (nexoframe.tokens.css), component không chứa @media nào. Mở devtools, bật "giảm chuyển động" để tự kiểm.
API & triển khai
| Prop | Mặc định | Quy ước |
|---|---|---|
| className, style | — | Cách duy nhất để đặt kích thước/hình dạng. |
| …mọi thuộc tính div khác | — | Truyền thẳng xuống Root. |
SkeletonProps = ComponentPropsWithoutRef<"div"> — không có prop riêng nào của Skeleton: không width, không height, không lines, không circle.