Loading Dots
Loading Dots indicate to users that content is actively loading into view.
Component Type
Indicator
Platform
Web
Component
Sana Canvas
Delivery Channels
Web
Version
16.1.7Experience Surfaces
Page Body Inline
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 {Graphic} from '@workday/canvas-kit-react/icon';
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';
const loadingStencil = createStencil({
base: {
background: system.color.surface.overlay.scrim,
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 {CanvasProvider} from '@workday/canvas-kit-react/common';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
export default () => {
return (
<CanvasProvider dir="rtl">
<LoadingDots />
</CanvasProvider>
);
};
Custom Shape
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {createStencil, createStyles} from '@workday/canvas-kit-styling';
import {base, system} from '@workday/canvas-tokens-web';
const styleOverrides = {
parentContainer: createStyles({
display: 'flex',
gap: system.gap.md,
}),
};
const loadingStencil = createStencil({
base: {
borderRadius: system.shape.full,
backgroundColor: system.color.surface.contrast.strong,
height: base.size1000,
width: base.size1000,
alignItems: 'center',
justifyContent: 'center',
display: 'flex',
},
});
export default () => {
return (
<div className={styleOverrides.parentContainer}>
<LoadingDots variant="inverse" cs={loadingStencil()} />
</div>
);
};
Custom Color and Animation
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styleOverrides = {
parentContainer: createStyles({
display: 'flex',
gap: system.gap.md,
}),
};
export default () => {
return (
<div className={styleOverrides.parentContainer}>
<LoadingDots
loadingDotColor={system.color.brand.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 {SecondaryButton} from '@workday/canvas-kit-react/button';
import {AccessibleHide, AriaLiveRegion} from '@workday/canvas-kit-react/common';
import {Flex} from '@workday/canvas-kit-react/layout';
import {LoadingDots} from '@workday/canvas-kit-react/loading-dots';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const styleOverrides = {
parentContainer: createStyles({
gap: system.gap.md,
}),
loadingStyles: createStyles({
backgroundColor: system.color.accent.muted.default,
padding: system.padding.sm,
}),
};
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.