Skip to main content
In Review

Spinner

A spinner is a rotating circle that indicates the status or state of completion for a process that’s part of a user flow, such as verifying personal information or sending a request. The circles can indicate that a process is underway.

Variants

Default

<svg
    class="gi-w-6 gi-h-6"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
>
    <g>
    <circle
        cx="12"
        cy="12"
        r="9.5"
        fill="none"
        stroke-width="3"
        stroke-linecap="round"
    >
        <animate
        attributeName="stroke-dasharray"
        dur="1.5s"
        calcMode="spline"
        values="0 150;42 150;42 150;42 150"
        keyTimes="0;0.475;0.95;1"
        keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
        repeatCount="indefinite"
        />
        <animate
        attributeName="stroke-dashoffset"
        dur="1.5s"
        calcMode="spline"
        values="0;-16;-59;-59"
        keyTimes="0;0.475;0.95;1"
        keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
        repeatCount="indefinite"
        />
    </circle>
    <animateTransform
        attributeName="transform"
        type="rotate"
        dur="2s"
        values="0 12 12;360 12 12"
        repeatCount="indefinite"
    />
    </g>
</svg>
{{ 
    govieSpinner({
        "size": "md"
    }) 
}}
<Spinner />

Button with a spinner

<button id="button" disabled="true" aria-disabled="true" class="gi-btn gi-btn-regular gi-btn-primary-disabled">
    Loading...
    <svg
        class="gi-w-6 gi-h-6"
        viewBox="0 0 24 24"
        xmlns="http://www.w3.org/2000/svg"
    >
        <g>
        <circle
            cx="12"
            cy="12"
            r="9.5"
            fill="none"
            stroke-width="3"
            stroke-linecap="round"
        >
            <animate
            attributeName="stroke-dasharray"
            dur="1.5s"
            calcMode="spline"
            values="0 150;42 150;42 150;42 150"
            keyTimes="0;0.475;0.95;1"
            keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
            repeatCount="indefinite"
            />
            <animate
            attributeName="stroke-dashoffset"
            dur="1.5s"
            calcMode="spline"
            values="0;-16;-59;-59"
            keyTimes="0;0.475;0.95;1"
            keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
            repeatCount="indefinite"
            />
        </circle>
        <animateTransform
            attributeName="transform"
            type="rotate"
            dur="2s"
            values="0 12 12;360 12 12"
            repeatCount="indefinite"
        />
        </g>
    </svg>
</button>
{{ 
    govieButton({
        "content": 'Loading... ' + govieSpinner(),
        "disabled": true
    }) 
}}
import { Button } from '@govie-ds/react';

<Button disabled={true}>
    Loading...
    <Spinner inline={true} />
</Button>
Loading...
<div>
    <button class="gi-btn gi-btn-primary gi-btn-regular">Open Modal</button>
</div>
<div class="gi-modal gi-modal-close">
    <div class="gi-modal-container">
        <div class="grid gap-4 px-4 justify-items-center">
            <svg
                class="gi-w-10 gi-h-10"
                viewBox="0 0 24 24"
                xmlns="http://www.w3.org/2000/svg"
            >
                <g>
                <circle
                    cx="12"
                    cy="12"
                    r="9.5"
                    fill="none"
                    stroke-width="3"
                    stroke-linecap="round"
                >
                    <animate
                    attributeName="stroke-dasharray"
                    dur="1.5s"
                    calcMode="spline"
                    values="0 150;42 150;42 150;42 150"
                    keyTimes="0;0.475;0.95;1"
                    keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
                    repeatCount="indefinite"
                    />
                    <animate
                    attributeName="stroke-dashoffset"
                    dur="1.5s"
                    calcMode="spline"
                    values="0;-16;-59;-59"
                    keyTimes="0;0.475;0.95;1"
                    keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1"
                    repeatCount="indefinite"
                    />
                </circle>
                <animateTransform
                    attributeName="transform"
                    type="rotate"
                    dur="2s"
                    values="0 12 12;360 12 12"
                    repeatCount="indefinite"
                />
                </g>
            </svg>
            <span>Loading...</span>
        </div>
    </div>
</div>
{{ 
govieModal({
    "html": "<div class='grid gap-4 px-4 justify-items-center'>"+govieSpinner()+"<span>Loading...</span></div>",
    "triggerButton": "<button>Open Modal</button>"
}) 
}}
import { Modal, Button, Spinner } from '@govie-ds/react';

<Modal triggerButton={<Button>Open Modal</Button>}  >
    <div className="grid gap-4 px-4 justify-items-center">
        <Spinner size="xl" />
        <span>Loading...</span>
    </div>
</Modal>

Usage

Best Practices

Here are some best practices for the usage of a Spinner component:

  1. Use spinners for short wait times (under 10 seconds):
    • Spinners are best for quick tasks like submitting a form or loading a small amount of data.
    • For longer waits (over 10 seconds), consider using progress bars or skeleton screens instead.
  2. Provide context and estimates:
    • Add helpful text explaining what's happening, e.g. "Loading your profile...".
    • If possible, give a general time estimate, e.g. "This may take a few seconds".
  3. Placement and visibility:
    • Centre the spinner within the loading area.
    • Ensure proper contrast against the background.
    • Add a slight delay (e.g. 100 ms) before showing the spinner to avoid flickering for very fast loads.
  4. Accessibility:
    • Use ARIA attributes like role="status" and aria-label to describe the loading state for screen readers.
    • Consider adding visually hidden text like "Now loading..." for accessibility.
  5. Alternative approaches:
    • For very quick loads (under 1 second), don't show a spinner at all.
    • Consider skeleton screens to show layout placeholders while content loads.
  6. Error handling:
    • Implement timeouts and error messaging if loading takes too long.
    • Provide options to retry or cancel the operation if it fails.
  7. Avoid overuse:
    • Don't use multiple spinners on the same page - use a single global indicator instead.
    • For component-level loading (e.g. in cards/dropdowns), consider skeleton loaders instead of spinners.

When to use this component

When not to use this component

Status

Figma Library
Considering
Local HTML
N/A
Global HTML
Beta
Global React
Beta