Navigation

Spinner

<oblyx-spinner> is an indeterminate loading indicator: an animated ring, with an optional visible label below it. Plain inline SVG plus a CSS rotation, not a canvas, so a consumer's own CSS can recolor or resize it the same way as any other Oblyx element.

Basic spinner

HTMLKotlin
<oblyx-spinner></oblyx-spinner>
oblyxSpinner()

Spinner versus progress bar: which to reach for

A spinner is role="status", a live region announcing a name such as "Loading": it makes no claim about how much work is left. Progress bar, set indeterminate, makes the different claim "there is a progress meter, and its value happens to be unknown" (role="progressbar" with no value attributes present). Reach for a spinner when there's genuinely no notion of percent complete, a page load or a background fetch; reach for progress bar, determinate, the moment you can compute a fraction, even a rough one, since that's strictly more informative to a waiting user.

Size

md is the default.

Spinner sizes

HTMLKotlin
<oblyx-spinner size="sm"></oblyx-spinner>
<oblyx-spinner size="md"></oblyx-spinner>
<oblyx-spinner size="lg"></oblyx-spinner>
<oblyx-spinner size="xl"></oblyx-spinner>
oblyxSpinner(size = OblyxSpinnerSize.SM)
oblyxSpinner(size = OblyxSpinnerSize.MD)
oblyxSpinner(size = OblyxSpinnerSize.LG)
oblyxSpinner(size = OblyxSpinnerSize.XL)

Shade

default uses the accent token. subtle uses the secondary text token, for a spinner that shouldn't compete visually with an accent-colored call to action nearby. on-media is for a spinner placed over a photo or video. inherit takes the ambient text color from wherever the spinner is placed and isn't pictured separately below, since it does nothing beyond what CSS already does when no color is set explicitly.

Spinner shade

HTMLKotlin
<oblyx-spinner shade="default"></oblyx-spinner>
<oblyx-spinner shade="subtle"></oblyx-spinner>
<div style="background: #1a1a2e; padding: var(--ox-spacing-3); border-radius: var(--ox-radius-element);">
  <oblyx-spinner shade="on-media"></oblyx-spinner>
</div>
oblyxSpinner(shade = OblyxSpinnerShade.DEFAULT)
oblyxSpinner(shade = OblyxSpinnerShade.SUBTLE)
div {
  style = "background: #1a1a2e; padding: var(--ox-spacing-3); border-radius: var(--ox-radius-element);"
  oblyxSpinner(shade = OblyxSpinnerShade.ON_MEDIA)
}

Accessible name

Three ways a spinner gets its accessible name, in priority order. An explicit aria-label wins outright. Otherwise, visible light content names the spinner via aria-labelledby, pointing at that same visible text, rather than duplicating it into a second aria-label copy some assistive tech would announce twice. With neither present, the spinner falls back to a hardcoded accessible name, "Loading".

Default: announces "Loading"

HTMLKotlin
<oblyx-spinner></oblyx-spinner>
oblyxSpinner()

Visible label names the spinner

Uploading files…
HTMLKotlin
<oblyx-spinner>Uploading files&hellip;</oblyx-spinner>
oblyxSpinner { +"Uploading files\u2026" }

Explicit aria-label overrides everything

HTMLKotlin
<oblyx-spinner aria-label="Loading search results"></oblyx-spinner>
oblyxSpinner(label = "Loading search results")

A spinner beside visible "Loading" text

A spinner that is the only indication a page is loading must be announced, which is exactly what the default fallback name achieves with zero setup. A decorative spinner placed next to text that already reads "Loading" is a different case: announcing the spinner too would read out "Loading. Loading." to a screen reader. Set an empty aria-label on the spinner itself in that case, so only the adjacent visible text is announced.

Spinner beside its own visible text

aria-label="" on the spinner suppresses its own announcement; the visible "Loading" text does the job instead.

Loading

HTMLKotlin
<p style="display: flex; align-items: center; gap: var(--ox-spacing-2);">
  <oblyx-spinner aria-label=""></oblyx-spinner>
  Loading
</p>
p {
  style = "display: flex; align-items: center; gap: var(--ox-spacing-2);"
  oblyxSpinner(label = "")
  +"Loading"
}

Reference

<oblyx-spinner>

AttributeTypeDefaultDescription
sizesmmdlgxlmdRing size.
shadedefaulton-mediasubtleinheritdefaultRing and label color. 'default' uses the accent token; 'on-media' is for a spinner placed over a photo or video; 'subtle' uses the secondary text token; 'inherit' takes the ambient text color from wherever the spinner is placed, doing nothing beyond what CSS already does when no color is set explicitly.
aria-labelstring | undefinedAccessible name override. Wins over a visible label; falls back to the hardcoded name "Loading" when neither is present.