A turning ring that says something is happening. It occupies an icon box and paints an icon amount of ink, so it drops into a button or a line of text in place of a glyph.
size is a number of pixels, and it names the box the spinner occupies rather than the diameter of the ring. Left out, the box measures 1em and follows the text around it.
vue
Loading… Follows small text
Loading… Follows large text
Loading… 32 pixels, whatever the text does
<script setup lang="ts">
import { VSpinner } from 'vectis-ui'
</script>
<template>
<div class="demo">
<!-- With no size the box measures 1em, so the spinner follows the text around it:
a container that sets a font-size sizes it without being told anything, which
is how it stays proportionate inside a button. -->
<p class="small"><VSpinner /> Follows small text</p>
<p class="large"><VSpinner /> Follows large text</p>
<!-- `size` is a number of pixels, and it is the BOX the spinner occupies, not the
diameter of the ring: the ring is drawn a little smaller inside it, at the
proportion an icon paints its ink at. -->
<p><VSpinner :size="32" /> 32 pixels, whatever the text does</p>
</div>
</template>
<style scoped>
.demo {
display: grid;
gap: var(--vectis-space-4);
}
.demo p {
display: flex;
align-items: center;
gap: var(--vectis-space-3);
margin: 0;
}
.small {
font-size: var(--vectis-text-body-sm-size);
}
.large {
font-size: var(--vectis-text-heading-3-size);
}
</style>
Colour
There is no colour prop: the ring is painted in currentcolor, so it takes the colour of the text it sits in.
vue
Loading… The colour of the text it sits in
Sending Sending
Retrying Retrying
<script setup lang="ts">
import { VSpinner } from 'vectis-ui'
</script>
<template>
<div class="demo">
<!-- There is no colour prop: the ring is painted in `currentcolor`, so it takes
the colour of the text around it. Set `color` on the spinner or on anything
above it, and it follows. -->
<p><VSpinner /> The colour of the text it sits in</p>
<p class="accent"><VSpinner label="Sending" /> Sending</p>
<p class="danger"><VSpinner label="Retrying" /> Retrying</p>
</div>
</template>
<style scoped>
.demo {
display: grid;
gap: var(--vectis-space-3);
}
.demo p {
display: flex;
align-items: center;
gap: var(--vectis-space-3);
margin: 0;
}
.accent {
color: var(--vectis-color-accent-text);
}
.danger {
color: var(--vectis-color-danger-text);
}
</style>
In place of an icon
The box is an icon's box, so a VIcon and a VSpinner given the same size are interchangeable. That is what lets VButton, VInput, VTextarea and VCombobox draw one at the size of the glyph it replaces.
vue
Searching the archive
Loading… Searching the archive
Loading…
<script setup lang="ts">
import { VButton, VIcon, VInput, VSpinner } from 'vectis-ui'
import { search } from 'vectis-ui/icons'
</script>
<template>
<div class="demo">
<!-- The spinner occupies an icon's box and paints an icon's amount of ink, so one
stands in for the other with nothing shifting on the line. A VIcon and a
VSpinner given the same size are interchangeable, box for box. -->
<p><VIcon :name="search" /> Searching the archive</p>
<p><VSpinner /> Searching the archive</p>
<!-- Which is what lets the controls draw their own: they set the icon size and get
a spinner the size of the glyph it replaces, with no ratio of their own. -->
<VButton class="control" loading>Saving</VButton>
<VInput class="control" label="Reference" model-value="INV-2481" loading />
</div>
</template>
<style scoped>
.demo {
display: grid;
justify-items: start;
gap: var(--vectis-space-4);
}
.demo p {
display: flex;
align-items: center;
gap: var(--vectis-space-3);
margin: 0;
}
.control {
inline-size: 14rem;
}
</style>
API
Props
Prop
Type
Default
size
number | string
none
A size in pixels, as a number or a numeric string, understood exactly as VIcon's: it is the box the spinner occupies, not the diameter of the ring, which is drawn slightly smaller inside it. Left out, the box measures 1em and follows the size of the text around it, which is how the spinner stays proportionate inside a button without being told anything.
label
string
none
What screen readers announce while it turns. It falls back to the design system dictionary, in the current language.