# Loading Skeleton (/components/feedback/loading-skeleton)



Use `LoadingSkeleton` when content is loading but its layout is known. Wrap the content that will
appear so the placeholder occupies the same space.

apps/docs/src/examples/loading-skeleton/basic.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Checkbox } from '@luke-ui/react/checkbox';
import { LoadingSkeleton } from '@luke-ui/react/loading-skeleton';
import { Text } from '@luke-ui/react/text';
import { useState } from 'react';

export default () => {
	const [isLoading, setIsLoading] = useState(true);

	return (
		<Box display="grid" gap="sp16" maxInlineSize="32rem">
			<Checkbox isSelected={isLoading} onChange={setIsLoading}>
				Show loading state
			</Checkbox>
			<Text>
				<LoadingSkeleton isLoading={isLoading}>Three items match your search.</LoadingSkeleton>
			</Text>
		</Box>
	);
};
```

Wrap text itself, rather than its parent, when it can span several lines. The placeholder then
follows each line without changing the layout.

## With components [#with-components]

Wrap an element to keep its dimensions while the skeleton covers it. Use this for controls, avatars,
and other content with a fixed shape.

apps/docs/src/examples/loading-skeleton/custom-dimensions.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { LoadingSkeleton } from '@luke-ui/react/loading-skeleton';

export default () => {
	return (
		<LoadingSkeleton>
			<Box blockSize="3rem" inlineSize="3rem" style={{ borderRadius: '9999px' }} />
		</LoadingSkeleton>
	);
};
```

Set `radius` when the direct child has square corners but a visible descendant has rounded corners.
A `TextField` is a typical case, because its input control has rounded corners inside the field
wrapper.

apps/docs/src/examples/loading-skeleton/border-radius.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Checkbox } from '@luke-ui/react/checkbox';
import { LoadingSkeleton } from '@luke-ui/react/loading-skeleton';
import { TextField } from '@luke-ui/react/text-field';
import { useState } from 'react';

export default () => {
	const [isLoading, setIsLoading] = useState(true);

	return (
		<Box display="flex" flexDirection="column" gap="sp16" maxInlineSize="20rem">
			<LoadingSkeleton isLoading={isLoading} radius="control">
				<TextField label="Email address" name="email" placeholder="you@example.com" />
			</LoadingSkeleton>
			<Checkbox isSelected={isLoading} onChange={setIsLoading}>
				Loading
			</Checkbox>
		</Box>
	);
};
```

## Loading state [#loading-state]

`isLoading` is `true` by default. Set it to `false` when the content is ready. The component then
returns its children without a wrapper.

```tsx
<LoadingSkeleton isLoading={isLoading}>
	<Button>Save changes</Button>
</LoadingSkeleton>
```

Use `LoadingSkeletonProvider` when one loading state controls a section. Its value overrides
`isLoading` on every descendant skeleton, so a section changes together.

apps/docs/src/examples/loading-skeleton/provider.tsx

```tsx
import { Box } from '@luke-ui/react/box';
import { Checkbox } from '@luke-ui/react/checkbox';
import { LoadingSkeleton, LoadingSkeletonProvider } from '@luke-ui/react/loading-skeleton';
import { Text } from '@luke-ui/react/text';
import { useState } from 'react';

export default () => {
	const [isLoading, setIsLoading] = useState(true);

	return (
		<Box display="grid" gap="sp16">
			<LoadingSkeletonProvider isLoading={isLoading}>
				<Box display="flex" flexWrap="wrap" gap="sp16">
					<Box display="grid" gap="sp4">
						<Text color="secondary" typography="caption">
							No local prop
						</Text>
						<Text>
							<LoadingSkeleton>Three items match your search.</LoadingSkeleton>
						</Text>
					</Box>
					<Box display="grid" gap="sp4">
						<Text color="secondary" typography="caption">
							isLoading
						</Text>
						<Text>
							<LoadingSkeleton isLoading>Results updated a moment ago.</LoadingSkeleton>
						</Text>
					</Box>
					<Box display="grid" gap="sp4">
						<Text color="secondary" typography="caption">
							{'isLoading={false}'}
						</Text>
						<Text>
							<LoadingSkeleton isLoading={false}>Nothing else to show.</LoadingSkeleton>
						</Text>
					</Box>
				</Box>
			</LoadingSkeletonProvider>
			<Checkbox isSelected={isLoading} onChange={setIsLoading}>
				Provider loading
			</Checkbox>
		</Box>
	);
};
```

## Element type [#element-type]

`LoadingSkeleton` renders a `span` by default. Set `elementType` when the parent requires another
element, such as an `li` inside a list.

apps/docs/src/examples/loading-skeleton/element.tsx

```tsx
import { LoadingSkeleton } from '@luke-ui/react/loading-skeleton';

export default () => {
	return (
		<ul>
			<LoadingSkeleton elementType="li">List item</LoadingSkeleton>
		</ul>
	);
};
```

## Accessibility [#accessibility]

While loading, `LoadingSkeleton` hides content from assistive technology, removes it from the tab
order, and blocks pointer input. It becomes available again when `isLoading` is `false`.

## API [#api]

### LoadingSkeletonProps [#loadingskeletonprops]

<ComponentPropsTable
  id="type-table-loading-skeleton.tsx-LoadingSkeletonProps"
  type="{
  &#x22;id&#x22;: &#x22;loading-skeleton.tsx-LoadingSkeletonProps&#x22;,
  &#x22;name&#x22;: &#x22;LoadingSkeletonProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for `LoadingSkeleton`.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;elementType&#x22;,
      &#x22;description&#x22;: &#x22;Element rendered while loading.&#x22;,
      &#x22;tags&#x22;: [
        {
          &#x22;name&#x22;: &#x22;default&#x22;,
          &#x22;text&#x22;: &#x22;'span'&#x22;
        }
      ],
      &#x22;type&#x22;: &#x22;ElementType | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;isLoading&#x22;,
      &#x22;description&#x22;: &#x22;Whether the skeleton is shown in place of `children`. Overridden by a `LoadingSkeletonProvider` ancestor.&#x22;,
      &#x22;tags&#x22;: [
        {
          &#x22;name&#x22;: &#x22;default&#x22;,
          &#x22;text&#x22;: &#x22;true&#x22;
        }
      ],
      &#x22;type&#x22;: &#x22;boolean | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;radius&#x22;,
      &#x22;description&#x22;: &#x22;Sets the semantic corner radius of the skeleton overlay. Use when the wrapped child has no\nradius of its own but a visual descendant does (e.g. wrapping a `TextField`).&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;\&#x22;detail\&#x22; | \&#x22;control\&#x22; | \&#x22;surface\&#x22; | \&#x22;overlay\&#x22; | \&#x22;full\&#x22; | undefined&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: false,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;deprecated&#x22;: false,
      &#x22;description&#x22;: &#x22;`LoadingSkeletonProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.&#x22;,
      &#x22;name&#x22;: &#x22;__nativePropsForwarding&#x22;,
      &#x22;required&#x22;: true,
      &#x22;simplifiedType&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;&#x22;
    }
  ]
}"
/>

### LoadingSkeletonProviderProps [#loadingskeletonproviderprops]

<ComponentPropsTable
  id="type-table-loading-skeleton.tsx-LoadingSkeletonProviderProps"
  type="{
  &#x22;id&#x22;: &#x22;loading-skeleton.tsx-LoadingSkeletonProviderProps&#x22;,
  &#x22;name&#x22;: &#x22;LoadingSkeletonProviderProps&#x22;,
  &#x22;description&#x22;: &#x22;Props for `LoadingSkeletonProvider`.&#x22;,
  &#x22;entries&#x22;: [
    {
      &#x22;name&#x22;: &#x22;children&#x22;,
      &#x22;description&#x22;: &#x22;&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;ReactNode&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;ReactNode&#x22;,
      &#x22;required&#x22;: true,
      &#x22;deprecated&#x22;: false
    },
    {
      &#x22;name&#x22;: &#x22;isLoading&#x22;,
      &#x22;description&#x22;: &#x22;Loading state applied to every descendant `LoadingSkeleton`, overriding their `isLoading` prop.&#x22;,
      &#x22;tags&#x22;: [],
      &#x22;type&#x22;: &#x22;boolean&#x22;,
      &#x22;simplifiedType&#x22;: &#x22;union&#x22;,
      &#x22;required&#x22;: true,
      &#x22;deprecated&#x22;: false
    }
  ]
}"
/>
