Shimmer to represent the structure of content while it loads. The application builds a restrained placeholder from ordinary layout and ShimmerItem blocks, and Shimmer sweeps one tilted highlight across the whole group for a coherent loading state.import {
Shimmer,
ShimmerItem,
ShimmerItemCornerRadius,
} from '@wearables-ui-toolkit/mrbd';
export function ListLoadingPlaceholder() {
return (
<Shimmer>
<div className="loading-row">
<ShimmerItem
className="loading-avatar"
cornerRadius={ShimmerItemCornerRadius.XLARGE}
/>
<div className="loading-copy">
<ShimmerItem className="loading-title" />
<ShimmerItem className="loading-detail" />
</div>
</div>
</Shimmer>
);
}
.loading-row {
display: flex;
gap: var(--uit-spacing-medium);
align-items: center;
}
.loading-copy {
display: grid;
flex: 1;
gap: var(--uit-spacing-small);
}
showShimmer when real content arrives. Shimmer then removes its visual treatment without changing the wrapper’s layout:import { Shimmer, ShimmerItem } from '@wearables-ui-toolkit/mrbd';
import { ArticleBody } from './ArticleBody';
export function Article({ isLoading }: { isLoading: boolean }) {
return (
<Shimmer showShimmer={isLoading}>
{isLoading ? <ShimmerItem className="loading-title" /> : <ArticleBody />}
</Shimmer>
);
}
import {
Shimmer,
ShimmerItem,
usePrefersReducedMotion,
} from '@wearables-ui-toolkit/mrbd';
export function QuietPlaceholder() {
const prefersReducedMotion = usePrefersReducedMotion();
return (
<Shimmer autoStart={!prefersReducedMotion}>
<ShimmerItem className="loading-title" />
</Shimmer>
);
}
div attributes and forward a ref to their root element. Props not listed below are spread onto that root.ShimmerShimmerProps.| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Placeholder content. One shared highlight sweeps everything inside. |
showShimmer | boolean | true | Applies the shimmer treatment. When false, children render unchanged. |
autoStart | boolean | true | Runs the sweep. When false, the highlight remains at its resting position. |
clipToChildren | boolean | false | Clips the sweep to the wrapper’s box rather than allowing it to overflow. |
repeatCount | number | -1 | Number of repeats after the first pass. A negative value repeats forever. |
repeatMode | ShimmerRepeatMode | ShimmerRepeatMode.RESTART | Restarts each repeat from the same side or reverses its direction. |
startDelayMs | number | 0 | Delay before the first sweep, in milliseconds. Negative values produce no delay. |
staticAnimationProgress | number \| null | null | Pins the sweep at a fixed position from 0 to 1 instead of animating. The toolkit clamps out-of-range values. |
className | string | '' | Class added to the wrapper. |
style | CSSProperties | {} | Inline styles applied to the wrapper. They merge after the component’s custom properties. |
ShimmerItemShimmerItemProps.| Prop | Type | Default | Description |
|---|---|---|---|
width | number \| string | — | Item width. A number is treated as pixels; prefer responsive CSS. |
height | number \| string | — | Item height. A number is treated as pixels; prefer responsive CSS. |
cornerRadius | ShimmerItemCornerRadius | ShimmerItemCornerRadius.MEDIUM | Semantic placeholder radius. |
className | string | '' | Class applied to the item. |
style | CSSProperties | {} | Inline styles applied to the item. They merge after width and height. |
ShimmerRepeatModeRESTART — every repeat sweeps in the same directionREVERSE — repeats alternate directionShimmerItemCornerRadiusSQUARE — no roundingXXSMALLXSMALLSMALLMEDIUMLARGEXLARGESQUARE maps to the matching corner-radius token. Choose the matching token when a placeholder block needs to remain concentric with the real component it represents.Shimmer renders its children once and masks that single subtree. It does not duplicate content, so ids, data attributes, and refs inside the placeholder remain unique. One tilted highlight travels across the wrapper, helping several items read as one loading surface rather than unrelated animations.ResizeObserver is unavailable, the toolkit measures the box once on mount. The wrapper is an inline-block; give it width through application layout or CSS when it should fill a row.clipToChildren when the placeholder sits in a tight region and its highlight needs to remain inside that box.startDelayMs controls only the delay before the first sweep. repeatCount counts repeats after that first pass, so a value of two produces three sweeps in total; the default negative value repeats forever. repeatMode restarts each repeat from the same edge or alternates its direction.showShimmer is on, the toolkit masks the wrapped content at a reduced base opacity, and the traveling highlight restores full opacity as it passes. This dimming belongs to the treatment rather than the animation, so it remains when the sweep is stopped.showShimmer={false} removes the complete treatment and renders children as ordinary full-opacity content. autoStart={false} keeps the treatment but parks the highlight at the start, leaving the content uniformly dimmed with no movement. Both values are inexpensive to toggle and preserve layout.staticAnimationProgress stops the animation and pins the highlight between 0 and 1, which supports reproducible screenshots and other deterministic rendering. The toolkit clamps values outside that range.ShimmerItem renders a solid block filled with var(--uit-color-loading-content) and uses the corner-radius token selected by cornerRadius. It has no intrinsic size, so the application provides width, height, or CSS. The item does not shrink in a flex row and keeps its assigned size.usePrefersReducedMotion and pass autoStart={false} or a fixed staticAnimationProgress when reduced motion is requested. This accessibility boundary prevents nonessential motion after the user has asked to limit it.ShimmerItem is a visual placeholder and is always aria-hidden, so assistive technology does not announce its blocks.Shimmer adds no role or accessible name. The application must expose loading status on the owning region, for example with a role="status" live region or aria-busy on the container being populated, and remove that status when content arrives.Shimmer while the treatment is active. The mask changes its rendered opacity and does not represent usable content.Shimmer inside another. One wrapper must own the complete placeholder region so the loading state has one coherent animation.