Loading Dots
Loading Dots indicate to users that content is actively loading into view.
Anatomy

- Default Loading Dots: Ideal for use on white backgrounds
- Lighter Variant: For use on gray, dark, or image-based backgrounds.
Usage Guidance
- Use Loading Dots to identify when a specific area of the page is loading (i.e. the content within a card).
- Motion should be applied to the Loading Dots to reinforce that the content on the page is loading behind the scenes.
- Avoid increasing the size of the Loading Dots to maintain consistency with other indicators accross the application.
- Always center the Loading Dots and position it close to where you want the user’s attention to be once loading is complete.
- Use for specific elements on a page that are still loading while other content has already loaded.
- If only a portion of the interface is displaying new content or being updated, place the Loading Dots in that specific part of the interface.
- In immediate response to an executed action when there is excessive time before the expected results occur.
- Ideally used on a white background.
When to Use
- Use on page elements where the visual layout/format of the content being loaded is unknown.
- Use to indicate processing, or that change will occur on the page (rather than loading UI elements).
When to Use Something Else
- Consider using a Skeleton if the visual layout/format of the content being loaded is known ahead of time (preferred).
Examples
Basic Example
Use Loading Dots to identify when a specific area of the page is loading (i.e. the content within a card).
import React from 'react';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
export default () => {
return <LoadingDots />;
};
Inverse Variant
Use the variant="inverse" prop when the loading dots are on a dark background or image.
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {createStencil, createStyles, px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Graphic} from '@workday/canvas-kit-react/icon';
const loadingStencil = createStencil({
base: {
background: system.color.bg.overlay,
alignItems: 'center',
justifyContent: 'center',
display: 'flex',
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '100%',
height: '100%',
},
});
const containerStyles = createStyles({
position: 'relative',
width: px2rem(200),
height: px2rem(200),
});
export default () => {
return (
<div className={containerStyles}>
<LoadingDots variant="inverse" cs={loadingStencil()} />
<Graphic
alt="A magnifying glass"
width={200}
src={{
url: 'https://picsum.photos/200',
}}
srcset="https://picsum.photos/200 200w, https://picsum.photos/200 200w, https://picsum.photos/800 800w, https://picsum.photos/1200 1200w"
/>
</div>
);
};
Right-to-Left (RTL)
import React from 'react';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {CanvasProvider} from '@workday/canvas-kit-react/common';
export default () => {
return (
<CanvasProvider dir="rtl">
<LoadingDots />
</CanvasProvider>
);
};
Custom Shape
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {system} from '@workday/canvas-tokens-web';
import {createStyles, createStencil} from '@workday/canvas-kit-styling';
const styleOverrides = {
parentContainer: createStyles({
display: 'flex',
gap: system.space.x4,
}),
};
const loadingStencil = createStencil({
base: {
borderRadius: system.shape.round,
backgroundColor: system.color.bg.contrast.strong,
height: 80,
width: 80,
alignItems: 'center',
justifyContent: 'center',
display: 'flex',
},
});
export default () => {
return (
<div className={styleOverrides.parentContainer}>
<LoadingDots variant="inverse" cs={loadingStencil()} />
</div>
);
};
Custom Color and Animation
import React from 'react';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {system} from '@workday/canvas-tokens-web';
import {createStyles} from '@workday/canvas-kit-styling';
const styleOverrides = {
parentContainer: createStyles({
display: 'flex',
gap: system.space.x4,
}),
};
export default () => {
return (
<div className={styleOverrides.parentContainer}>
<LoadingDots loadingDotColor={system.color.fg.primary.default} animationDurationMs="60ms" />
</div>
);
};
Custom Styles
Loading Dots supports custom styling via the cs prop. For more information, check our
“How To Customize Styles”.
Custom styling is also supported through the Loading Dots documented props below.
Accessibility
Sometimes, letting users know when content has finished loading is just as important as asking users
to “please wait” while content is loading. The disappearance of an animation is information that
might need description. In this example, we are using AriaLiveRegion and AccessibleHide
components included in Canvas to describe both the appearance and disappearance of LoadingDots.
- When idle, render an empty live region
- When loading, render
LoadingDotsinside the live region, - When complete, render
AccessibleHideinside the live region expressing “Complete!” - We can assign a name to
AriaLiveRegioncomponent by passing inaria-label="Loading" - We can declare
LoadingDotsa labeled graphic by passingrole="img"andaria-label="Please wait..."into the component
import React from 'react';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {system} from '@workday/canvas-tokens-web';
import {Flex} from '@workday/canvas-kit-react/layout';
import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {createStyles} from '@workday/canvas-kit-styling';
import {AccessibleHide, AriaLiveRegion} from '@workday/canvas-kit-react/common';
const styleOverrides = {
parentContainer: createStyles({
gap: system.space.x4,
}),
loadingStyles: createStyles({
backgroundColor: system.color.bg.muted.default,
padding: system.space.x3,
}),
};
export default () => {
const [loadingState, setLoadingState] = React.useState('idle');
React.useEffect(() => {
const timer = setTimeout(() => {
if (loadingState === 'loading') {
setLoadingState('success');
}
}, 4000);
return () => {
clearTimeout(timer);
};
}, [loadingState]);
const handleLoad = () => {
setLoadingState('loading');
};
return (
<Flex cs={styleOverrides.parentContainer}>
<SecondaryButton onClick={handleLoad}>Start</SecondaryButton>
<AriaLiveRegion aria-label="Loading">
{loadingState === 'loading' && (
<LoadingDots
cs={styleOverrides.loadingStyles}
role="img"
variant="inverse"
aria-label="Please wait..."
/>
)}
{loadingState === 'success' && <AccessibleHide>Complete.</AccessibleHide>}
</AriaLiveRegion>
</Flex>
);
};
Component API
LoadingDots
A simple component that displays three horizontal dots, to be used when some data is loading.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
loadingDotColor | string | Applies backgroundColor to loading dots, intended for use with the circle variant design on grey/dark/image-based backgrounds. | |
animationDurationMs | string | Duration of the loading animation in milliseconds. | |
variant | 'inverse' | ||
cs | | The | |
children | React.ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Accessibility Guidelines
- Loading Dots should announce to users using a screen reader that a page or a portion of the page is currently being loaded.
Content Guidelines
- Loading Dots typically should not appear long enough to require any content.
- In rare use cases it may be helpful to support the Loading Dots with a brief statement describing specifically what is currently loading.
- It’s recommended to keep loading UI descriptions a short, single line sentence as the user may have very little time to read it.
Anatomy

- Default: Darker fill for light backgrounds.
- Inverse: Lighter fill for higher contrast on dark backgrounds.
Usage Guidance
When to Use
- Use Loading Dots to indicate that a page or subset of a page is loading into view when the end layout and sizing of the UI elements coming into view is unknown.
- Use Loading Dots in immediate response to an executed action when there is excessive time before the expected results occur (e.g., Loading Dots may appear in a Button).
When to Consider Something Else
- Consider using a Skeleton if the exact end layout and sizing of the UI elements coming into view are known during the fetching and rendering processes.
- Consider using a Progress Bar for illustrating the duration of a task or process, not for loading content into a page.
- Consider using default operating system pull-to-refresh paradigms when the page is unscrolled and the user pulls down.

Behaviors
Motion
The dots increase and decrease in size from left to right in a continuous loop.
Variations
Placement
Always center the Loading Dots and position close to where you want the user’s attention to be once loading is complete. If only a portion of the interface is displaying new content or being updated, place the Loading Dots in that specific part of the interface. When surrounding UI elements are available on the screen, the default padding recommendation is 40 pixels.

When content loads in, shift the Loading Dots downward first (~100ms), then quickly fade in the loaded content (~100ms). Staggering prevents the Loading Dots from briefly overlaying the content as the content fades in. Continue displaying the loading indicator below the content if there is more content loading. Only use Loading Dots to display content coming in top down if it is truly smooth every time and doesn’t cause content shifting.
Otherwise, wait until all content is ready in fetching and then display all content at once, centering the Loading Dots on the page until then.

Sizing
The size of standalone Loading Dots should never change across different experiences in the app in order to maintain overall consistency. The size of nested Loading Dots may be adjusted within components, such as Buttons, to fit the necessary size restrictions.
Background
The background behind the Loading Dots is not supported, rather the fill color within the dots adapts on lighter versus darker backgrounds between the default and inverse versions.
Component API
Coming soon!
Accessibility Guidelines
On a screen reader, Loading Dots should announce to users that a page or a portion of the page is currently being loaded.
Content Guidelines
Please refer to Loading Dots in the Canvas UX Content Guide for further information on including additional content during loading.
Anatomy

- Default: Darker fill for light backgrounds.
- Inverse: Lighter fill for higher contrast on dark backgrounds.
Usage Guidance
When to Use
- Use Loading Dots to indicate that a page or subset of a page is loading into view when the end layout and sizing of the UI elements coming into view is unknown.
- Use Loading Dots in immediate response to an executed action when there is excessive time before the expected results occur (e.g., Loading Dots may appear in a Button).
When to Consider Something Else
- Consider using a Skeleton if the exact end layout and sizing of the UI elements coming into view are known during the fetching and rendering processes.
- Consider using a Progress Bar for illustrating the duration of a task or process, not for loading content into a page.
- Consider using default operating system pull-to-refresh paradigms when the page is unscrolled and the user pulls down.

Behaviors
Motion
The dots increase and decrease in size from left to right in a continuous loop.
Variations
Placement
Always center the Loading Dots and position close to where you want the user’s attention to be once loading is complete. If only a portion of the interface is displaying new content or being updated, place the Loading Dots in that specific part of the interface. When surrounding UI elements are available on the screen, the default padding recommendation is 40 pixels.

When content loads in, shift the Loading Dots downward first (~100ms), then quickly fade in the loaded content (~100ms). Staggering prevents the Loading Dots from briefly overlaying the content as the content fades in. Continue displaying the loading indicator below the content if there is more content loading. Only use Loading Dots to display content coming in top down if it is truly smooth every time and doesn’t cause content shifting.
Otherwise, wait until all content is ready in fetching and then display all content at once, centering the Loading Dots on the page until then.

Sizing
The size of standalone Loading Dots should never change across different experiences in the app in order to maintain overall consistency. The size of nested Loading Dots may be adjusted within components, such as Buttons, to fit the necessary size restrictions.
Background
The background behind the Loading Dots is not supported, rather the fill color within the dots adapts on lighter versus darker backgrounds between the default and inverse versions.
Component API
Coming soon!
Accessibility Guidelines
On a screen reader, Loading Dots should announce to users that a page or a portion of the page is currently being loaded.
Content Guidelines
Please refer to Loading Dots in the Canvas UX Content Guide for further information on including additional content during loading.
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.