Skeleton
Shimmering loading placeholders for text, avatars, and cards.
Rendering Skeleton…
Installation
Copy the source into your project with the CLI. It lands under @/components/ui and is yours to edit.
npx mlola-ui add skeletonUsage
import { SkeletonAvatar, SkeletonRegion, SkeletonText } from "@/components/ui/skeleton";
export default function Example() {
return (
<SkeletonRegion label="Loading profile">
<div className="ml-cluster">
<SkeletonAvatar size={40} />
<SkeletonText lines={2} />
</div>
</SkeletonRegion>
);
}Styling comes from the engine stylesheet and the nearest theme. Set it once at the root:
<html data-theme="graphite" data-mode="light">HTML
The markup the example above renders, exactly. It needs no script: write it from any language or template.
<div class="ml-skeleton-region" role="status" aria-busy="true">
<span class="ml-visually-hidden">Loading profile</span>
<div class="ml-cluster">
<div class="ml-skeleton ml-skeleton-avatar" aria-hidden="true" style="width:40px;height:40px;border-radius:50%"></div>
<div class="ml-skeleton-text" aria-hidden="true">
<div class="ml-skeleton ml-skeleton-line" data-rounded=""></div>
<div class="ml-skeleton ml-skeleton-line" data-rounded=""></div>
</div>
</div>
</div>Classes and attributes
A class names each element; data-* and aria-* attributes carry its variant and state. The values listed are the ones the stylesheet draws; the default needs no attribute.
| Class | Attributes |
|---|---|
ml-skeleton | data-rounded="none" |
ml-skeleton-text | — |
ml-skeleton-line | — |
ml-skeleton-avatar | — |
ml-skeleton-card | — |
ml-skeleton-card-media | — |
ml-skeleton-card-title | — |
ml-skeleton-region | — |
Accessibility and theming
- Semantic elements, accessible names and state relationships are part of the contract.
- Keyboard, pointer and touch paths are operable; focus stays visible in every theme.
- Light and dark modes pass WCAG AA contrast in all 5 canonical themes.
- Reduced motion and forced colors keep meaning and operation.