Skeleton
Lightweight, accessible skeleton (placeholder) component for displaying loading states. Can be used as lines, text, avatars, buttons, or cards while content is loading.
Usage
Basic usage
import { Skeleton } from '@nofinite/nui';
<Skeleton width="100%" size="md" />;
With typical interaction
<Skeleton circle size="lg" width={56} />
<Skeleton animated={false} size="md" width="100%" />
Variants
Skeleton is primarily visual, with optional circle shapes and animation.
<Skeleton size="md" />
<Skeleton circle size="lg" />
<Skeleton animated={false} />
Available variants:
default– standard rectangular skeletoncircle– circular skeleton for avatars or iconsanimated– shimmer animation (respects prefers-reduced-motion)
Guidelines:
- Use
circlefor avatars or round elements. - Disable animation (
animated={false}) for reduced motion preferences or static placeholders.
Sizes
<Skeleton size="xs" />
<Skeleton size="sm" />
<Skeleton size="md" />
<Skeleton size="lg" />
<Skeleton size="xl" />
Available sizes:
xs– 8px heightsm– 12px heightmd– 16px height (default)lg– 24px heightxl– 32px height
States
Skeleton does not have interactive states but supports visual variations:
<Skeleton animated />
<Skeleton animated={false} />
<Skeleton circle />
animated– shows shimmer animationcircle– renders as a circleariaHidden– controls accessibility visibility (defaulttrue)
Native Props / Composition
Skeleton forwards standard HTML props and supports styling via className and style:
<Skeleton
aria-hidden={false}
role="presentation"
className="custom-skeleton"
style={{ width: 150 }}
/>
Props
| Prop | Type | Default | Description | ||||
|---|---|---|---|---|---|---|---|
size | `"xs" | "sm" | "md" | "lg" | "xl"` | md | Visual thickness / height of the skeleton |
width | `number | string` | — | Width of the skeleton (e.g., 200, "50%") | |||
animated | boolean | true | Enable shimmer animation | ||||
circle | boolean | false | Renders as a circle | ||||
ariaHidden | boolean | true | Controls visibility to assistive technologies | ||||
className | string | "" | Additional custom class names | ||||
style | React.CSSProperties | — | Inline styles | ||||
children | React.ReactNode | — | Not used; skeleton is self-contained | ||||
...rest | React.HTMLAttributes<HTMLElement> | — | Any other forwarded native attributes |
Behavior Notes
widthprop automatically converts numbers to pixels- Shimmer respects user preferences for reduced motion
- Can be composed using helper components:
Skeleton.Text,Skeleton.Paragraph,Skeleton.Avatar,Skeleton.Button,Skeleton.Card
<Skeleton.Paragraph lines={3} />
<Skeleton.Avatar size={56} />
Accessibility
- Skeleton renders as
<span role="presentation">by default - For screen readers, set parent
aria-busy="true"andaria-live="polite"to indicate loading - Individual skeletons can use
aria-hidden=trueto be ignored by assistive tech
Example:
<div aria-busy="true" aria-live="polite">
<Skeleton width="100%" size="md" />
</div>
Layout
- Inline by default, block if width is specified
- Supports full-width skeletons via
width="100%" - Circle variant maintains aspect ratio based on width/height
<Skeleton style={{ width: "100%" }} />
<Skeleton circle width={56} />
Best Practices
Do
- Use
Skeletonto indicate loading for text, avatars, buttons, or cards - Wrap content containers with
aria-busy="true"for proper accessibility - Combine with helper components for structured placeholders:
Text,Paragraph,Avatar,Button,Card
Don’t
- Rely on Skeleton for interactive feedback
- Use it for content that is immediately available (avoid unnecessary placeholders)
- Ignore accessibility – always manage
aria-hiddenand parent loading state