# Skeleton

A skeleton lets people know that a section of content is loading without blocking other parts of the page.

## 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.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-skeleton--default.tsx)

```tsx
// 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;
```

## 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

```ts
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

```ts
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.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Animation

Source: Fluent, adapted for CoreAI.

You can specify the animation style of the Skeleton.
      The default is 'wave' with the alternative being 'pulse'

[Download source](/coreai-design-system/source/examples/components-skeleton--animation.tsx)

```tsx
// 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

Source: Fluent, adapted for CoreAI.

You can specify the appearance of the Skeleton.
      This is useful for instances where you want to render a Skeleton with a MaterialOS theme

[Download source](/coreai-design-system/source/examples/components-skeleton--appearance.tsx)

```tsx
// 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

Source: Fluent, adapted for CoreAI.

You can make more complex wireframes using the basic building blocks of the Skeleton.

[Download source](/coreai-design-system/source/examples/components-skeleton--row.tsx)

```tsx
// 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

Source: Fluent, adapted for CoreAI.

The shape of the `SkeletonItem` can be set to circle, rectangle, or square.

[Download source](/coreai-design-system/source/examples/components-skeleton--shape.tsx)

```tsx
// 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

Source: Fluent, adapted for CoreAI.

You can specify the size of the `SkeletonItem` by using the `size` prop.
      The size is a number that represents the height of the `SkeletonItem` in pixels

[Download source](/coreai-design-system/source/examples/components-skeleton--size.tsx)

```tsx
// 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;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=114502-121706)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/skeleton/usage)