Skeleton
View .mdA skeleton lets people know that a section of content is loading without blocking other parts of the page.
Default
Loading interactive example. Full source is available below.
View example source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { SkeletonProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
export const Default = (props: Partial<SkeletonProps>): JSXElement => (<Skeleton {...props} aria-label="Loading Content">
<SkeletonItem />
</Skeleton>);
export default Default;
Resources
Best practices
Do
- Use skeletons for gradually loading structured content that takes longer than one second.
- Prefer the wave animation in most cases.
- Keep the placeholder simple and represent only consistent, high-level content structure.
Don't
- Use skeletons for fixed layout elements.
- Use skeletons for long-running processes.
- Use a skeleton when the eventual content structure is unknown; use a progress bar or spinner.
Behavior and states
- Skeletons have wave and pulse animation styles.
- Wave is the default animation and provides the smoothest transition.
- Keep skeleton animations in sync when staggered loading is unavoidable.
- Use skeletons for dynamic content, not fixed parts of a layout.
API referenceGenerated CoreAI prop and type summaries
API
Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.
Skeleton API
Skeleton component - TODO: add more docs
interface SkeletonProps {
/**
* The animation type for the Skeleton
*/
animation?: "wave" | "pulse";
/**
* Sets the appearance of the Skeleton.
*/
appearance?: "opaque" | "translucent";
as?: "div" | "span";
children?: any;
className?: string;
ref?: Ref<HTMLSpanElement>;
/**
* Sets the shape of the SkeletonItems inside the Skeleton.
* This value can be overridden by the individual SkeletonItem's `shape` prop.
*/
shape?: "circle" | "square" | "rectangle";
/**
* Sets the size of the SkeletonItems inside the Skeleton in pixels.
* Size is restricted to a limited set of values recommended for most uses (see SkeletonItemSize).
* This value can be overridden by the individual SkeletonItem's `size` prop.
*/
size?: 16 | 20 | 24 | 28 | 32 | 36 | 40 | 48 | 56 | 64 | 72 | 96 | 120 | 128 | 8 | 12 | 14 | 22 | 52 | 92;
style?: CSSProperties;
/**
* Sets the width value of the skeleton wrapper.
* @deprecated Use `className` prop to set width
*/
width?: string | number;
}
SkeletonItem API
interface SkeletonItemProps {
/**
* Sets the animation of the SkeletonItem
* @default wave
*/
animation?: "wave" | "pulse";
/**
* Sets the appearance of the SkeletonItem
* @default opaque
*/
appearance?: "opaque" | "translucent";
as?: "div" | "span";
children?: any;
className?: string;
ref?: Ref<HTMLSpanElement>;
/**
* Sets the shape of the SkeletonItems inside the Skeleton.
* This value can be overridden by the individual SkeletonItem's `shape` prop.
*/
shape?: "circle" | "square" | "rectangle";
/**
* Sets the size of the SkeletonItems inside the Skeleton in pixels.
* Size is restricted to a limited set of values recommended for most uses (see SkeletonItemSize).
* This value can be overridden by the individual SkeletonItem's `size` prop.
*/
size?: 16 | 20 | 24 | 28 | 32 | 36 | 40 | 48 | 56 | 64 | 72 | 96 | 120 | 128 | 8 | 12 | 14 | 22 | 52 | 92;
style?: CSSProperties;
}
Implementation
CoreAI 0.12.0; Fluent 9.74.9.
Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.
Animation
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { SkeletonProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
invertedWrapper: {
backgroundColor: tokens.colorNeutralBackground1,
paddingTop: '50px',
paddingBottom: '50px',
},
});
export const Animation = (props: Partial<SkeletonProps>): JSXElement => {
const styles = useStyles();
return (<div className={styles.invertedWrapper}>
<Field validationMessage="Wave animation" validationState="none">
<Skeleton {...props} aria-label="Loading Content">
<SkeletonItem />
</Skeleton>
</Field>
<Field validationMessage="Pulse animation" validationState="none">
<Skeleton {...props} animation="pulse" aria-label="Loading Content">
<SkeletonItem />
</Skeleton>
</Field>
</div>);
};
export default Animation;
Appearance
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { SkeletonProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
invertedWrapper: {
backgroundColor: tokens.colorNeutralBackground1,
paddingTop: '50px',
paddingBottom: '50px',
},
});
export const Appearance = (props: Partial<SkeletonProps>): JSXElement => {
const styles = useStyles();
return (<div className={styles.invertedWrapper}>
<Field validationMessage="Opaque Appearance" validationState="none">
<Skeleton {...props} aria-label="Loading Content">
<SkeletonItem />
</Skeleton>
</Field>
<Field validationMessage="Translucent Appearance" validationState="none">
<Skeleton {...props} appearance="translucent" aria-label="Loading Content">
<SkeletonItem />
</Skeleton>
</Field>
</div>);
};
export default Appearance;
Row
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { SkeletonProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
invertedWrapper: {
backgroundColor: tokens.colorNeutralBackground1,
},
firstRow: {
alignItems: 'center',
display: 'grid',
paddingBottom: '10px',
position: 'relative',
gap: '10px',
gridTemplateColumns: 'min-content 80%',
},
secondThirdRow: {
alignItems: 'center',
display: 'grid',
paddingBottom: '10px',
position: 'relative',
gap: '10px',
gridTemplateColumns: 'min-content 20% 20% 15% 15%',
},
});
export const Row = (props: Partial<SkeletonProps>): JSXElement => {
const styles = useStyles();
return (<div className={styles.invertedWrapper}>
<Skeleton {...props} size={20} aria-label="Loading Content">
<div className={styles.firstRow}>
<SkeletonItem shape="circle" size={24}/>
<SkeletonItem shape="rectangle"/>
</div>
<div className={styles.secondThirdRow}>
<SkeletonItem shape="circle" size={24}/>
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
</div>
<div className={styles.secondThirdRow}>
<SkeletonItem shape="square" size={24}/>
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
<SkeletonItem />
</div>
</Skeleton>
</div>);
};
export default Row;
Shape
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
invertedWrapper: {
background: tokens.colorNeutralBackground1,
display: 'flex',
padding: tokens.spacingHorizontalXL,
},
row: {
display: 'grid',
gap: tokens.spacingHorizontalL,
gridTemplateColumns: '1fr 150px 1fr',
},
});
export const Shape = (): JSXElement => {
const styles = useStyles();
return (<div className={styles.invertedWrapper}>
<Skeleton className={styles.row} aria-label="Loading Content">
<SkeletonItem size={64} shape="circle"/>
<SkeletonItem size={64} shape="rectangle"/>
<SkeletonItem size={64} shape="square"/>
</Skeleton>
</div>);
};
export default Shape;
Size
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Skeleton } from "@coreai-ds/react-components";
import { SkeletonItem } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
wrapper: {
display: 'flex',
background: tokens.colorNeutralBackground1,
flexDirection: 'column',
padding: tokens.spacingHorizontalXL,
gap: tokens.spacingVerticalL,
},
innerWrapper: {
display: 'grid',
alignItems: 'center',
gridTemplateColumns: '25px 1fr',
gridGap: tokens.spacingHorizontalS,
},
});
const SIZES = [8, 12, 14, 16, 20, 22, 24, 28, 32, 36, 40, 48, 52, 56, 64, 72, 92, 96, 120, 128] as const;
export const Size = (): JSXElement => {
const styles = useStyles();
return (<div className={styles.wrapper}>
{SIZES.map(size => (<div key={size} className={styles.innerWrapper}>
<Text align="center">{size}</Text>
<Skeleton aria-label="Loading Content">
<SkeletonItem size={size}/>
</Skeleton>
</div>))}
</div>);
};
export default Size;