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.
Figma Library | Local HTML | Global HTML | React |
---|---|---|---|
considering | not-available | beta | beta |
<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>
Modal with a spinner
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:
- 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.
- 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".
- 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.
- 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.
- 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.
- Error handling:
- Implement timeouts and error messaging if loading takes too long.
- Provide options to retry or cancel the operation if it fails.
- 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.