Workday Canvas

Loading Dots

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

v14.2.34
Install
yarn add @workday/canvas-kit-react

Anatomy

Image of a Loading Dots with annotation markers.

  1. Default Loading Dots: Ideal for use on white backgrounds
  2. 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.

A magnifying glass
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 LoadingDots inside the live region,
  • When complete, render AccessibleHide inside the live region expressing “Complete!”
  • We can assign a name to AriaLiveRegion component by passing in aria-label="Loading"
  • We can declare LoadingDots a labeled graphic by passing role="img" and aria-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.

NameTypeDescriptionDefault
loadingDotColorstring

Applies backgroundColor to loading dots, intended for use with the circle variant design on grey/dark/image-based backgrounds.

animationDurationMsstring

Duration of the loading animation in milliseconds.

variant'inverse'
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use {@link mergeStyles } instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';

// ...

// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.

return (
 <Element
   {...handleCsProp(elemProps, [
     myStyles,
     myModifiers({ size: 'medium' }),
     myVars({ backgroundColor: 'red' })
   ])}
 >
   {children}
 </Element>
)
childrenReact.ReactNode
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.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 as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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.

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.

On this Page: