Basic Components
Spinner
Spinner indicates that something is in progress. The ring is sized in em, so it scales with the size prop and lines up with text.
Basic usage
Spinner indicates that something is in progress. Give it an aria-label so the busy state has a name, since the ring itself carries no text.
<Spinner aria-label="Loading"/>It renders role="status", so assistive technology announces the label when the spinner appears.
Sizes
The ring is one em square, so it scales with the size prop and lines up with text of the same size.
<Row itemsCenter flexWrap> <Spinner xs aria-label="Loading"/> <Spinner sm aria-label="Loading"/> <Spinner aria-label="Loading"/> <Spinner lg aria-label="Loading"/> <Spinner xl aria-label="Loading"/></Row>Appearances
The ring is drawn in the current text colour, so an appearance prop colours it directly.
<Row itemsCenter flexWrap> <Spinner primary aria-label="Loading"/> <Spinner accent aria-label="Loading"/> <Spinner secondary aria-label="Loading"/> <Spinner tertiary aria-label="Loading"/> <Spinner success aria-label="Loading"/> <Spinner danger aria-label="Loading"/> <Spinner warning aria-label="Loading"/> <Spinner info aria-label="Loading"/></Row>Variants
An appearance only becomes a colour through a variant, so Spinner carries the same outline / filled / ghost axis as everything else. It has no background of its own, so the variant does one thing here: it picks which colour of the appearance the ring paints in.
outline, the default, uses the appearance's own colour, for a spinner on a plain surface. filled uses the "on this fill" colour, for a spinner sitting on a filled surface of the same appearance.
<Col> <Row itemsCenter flexWrap> <Spinner danger aria-label="Loading"/> <Spinner success aria-label="Loading"/> <Spinner info aria-label="Loading"/> </Row> <Row flexWrap> <Card danger filled wFit><Spinner danger filled aria-label="Loading"/></Card> <Card success filled wFit><Spinner success filled aria-label="Loading"/></Card> <Card info filled wFit><Spinner info filled aria-label="Loading"/></Card> </Row></Col>Most of the time you do not need either. With no appearance prop the Spinner inherits the colour of whatever it sits in, which is what makes it readable inside a filled Badge, Card or Button without being told anything.
Rebuilding index
<Row itemsCenter flexWrap> <Badge info filled><Spinner xs aria-label="Loading"/> Syncing</Badge> <Card sm filled secondary wFit> <Row itemsCenter> <Spinner sm aria-label="Loading"/> <Text sm>Rebuilding index</Text> </Row> </Card></Row>Setting an appearance that matches the surface you are on is the one thing to avoid: <Spinner secondary> inside a secondary filled Card resolves to the outline colour, which is the surface's own colour, so the ring disappears.
Button and IconButton render this same component for their loading prop, so there is one spinner in the library and restyling theme.spinner restyles both. That state is documented where it is used, on Button and IconButton.
Spinner honours prefers-reduced-motion: the animation stops for users who ask for less motion.
Inline with text
Because the ring is sized in em, it matches the surrounding text without any manual tuning.
Checking availability…
<Row itemsCenter> <Spinner sm aria-label="Loading"/> <Text sm secondary>Checking availability…</Text></Row>Spinner Props
| Prop | Category | Default | Description |
|---|---|---|---|
accent | Appearance | Accent color appearance (rose) | |
danger | Appearance | Danger color appearance (red) | |
info | Appearance | Info color appearance (cyan) | |
inheritAppearance | Appearance | ✓ | Inherit appearance from parent — suppresses own data-appearance/data-variant, uses parent's CSS variables |
primary | Appearance | Primary color appearance (gray) | |
secondary | Appearance | Secondary color appearance (gray) | |
success | Appearance | Success color appearance (green) | |
tertiary | Appearance | Tertiary color appearance | |
warning | Appearance | Warning color appearance (amber) | |
margin | Margin | Enable margin on all sides | |
marginB | Margin | Enable only bottom margin | |
marginT | Margin | Enable only top margin | |
marginX | Margin | Enable only horizontal (inline) margin | |
marginY | Margin | Enable only vertical (block) margin | |
noMargin | Margin | ✓ | Disable margin (reset to 0) |
lg | Size | Large size | |
md | Size | ✓ | Medium size (default) |
sm | Size | Small size | |
xl | Size | Extra large size | |
xs | Size | Extra small size | |
filled | Variant | Filled variant - solid background with contrasting text color | |
ghost | Variant | Ghost variant - transparent background, no border, appearance-colored text, tinted hover background | |
outline | Variant | ✓ | Outline variant - transparent background with border and colored text (default) |
Layout & utility props (gap, padding, hide, items, justify, ...) — documented on Common Props
| Prop | Category | Default | Description |
|---|---|---|---|
block | Display | Block display - takes full width, new line | |
contents | Display | Contents display - element's box is removed, children display as if parent didn't exist | |
flex | Display | Flex display - flexbox container | |
grid | Display | Grid display - CSS grid container | |
hidden | Display | Hidden display - element is not visible | |
inline | Display | Inline display - flows with text | |
inlineBlock | Display | ✓ | Inline-block display - inline but with block properties |
inlineFlex | Display | Inline-flex display - inline flexbox container | |
inlineGrid | Display | Inline-grid display - inline grid container | |
table | Display | Table display - behaves like table element | |
tableCell | Display | Table-cell display - behaves like td element | |
desktopHide | Hide | Hide element on desktop devices and below (max-desktop: 80rem) | |
mobileHide | Hide | Hide element on mobile devices and below (max-mobile: 48rem) | |
tabletHide | Hide | Hide element on tablet devices and below (max-tablet: 64rem) |