<!-- GENERATED by scripts/build-llms.mjs from llms/overlays.md — do not edit this file. -->

# `lr-spinner`

- **Import** `import '@aceshooting/lyra-ui/components/lr-spinner.js';` (stable tag alias; registers the tag)
- **Class** `LyraSpinner`, also available unregistered from `@aceshooting/lyra-ui/components/overlays/spinner/spinner.class.js`
- **Family** `components/overlays/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
- **Deprecations** none
- **Optional peers** none
- **Themeable via** 4 parts, 7 custom properties — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-spinner`

An indeterminate busy indicator with a localized, deliberately non-live `role="progressbar"`
name. Mounting ordinary loading UI therefore does not create a false status announcement.

**Properties:** `labelPlacement: 'none' | 'after' = 'none'` (attribute `label-placement`, reflected)
and `accessibleLabel: string | null = null` (attribute **`aria-label`**, not `accessible-label`) —
names `[part="base"]`'s `role="progressbar"`; unset falls back to the localized "Loading…".

**Events:** none.

**Slots:** default — optional label text. `label-placement="after"` renders it inline next to the
indicator and its visible accessible text becomes the progressbar name unless `aria-label`
overrides it. Hidden, inert, `display:none`, `content-visibility:hidden`, and `aria-hidden`
descendants are excluded from that name. A `visibility:hidden|collapse` wrapper suppresses its own
text while a descendant that restores `visibility:visible` remains part of the name.
These rules and live mutation tracking cross nested forwarding slots, including assigned-node
replacement; no wrapper re-render is required.
`'none'` (the default) applies the native `hidden` state to the label wrapper, removing it from both
rendering and the accessibility tree; the progressbar then uses `aria-label` or the localized
"Loading…" fallback.

**CSS parts:** `base` and `spinner` are aliases on the same indeterminate `role="progressbar"`
outer wrapper (no `aria-valuenow` and no live-region semantics);
`spinner-indicator` is the animated `aria-hidden` ring, and `label` is the default-slot wrapper.

**Themeable custom properties:** `--lr-spinner-size` (default `var(--lr-size-1-25rem)` — both
dimensions), `--lr-spinner-track-width` (default `var(--lr-border-width-medium)` — ring thickness),
`--lr-spinner-duration` (default `var(--lr-transition-ambient)` — the duration _and_ easing of one
full rotation; the animation is dropped entirely under `prefers-reduced-motion: reduce`). The ring
colors come from `--lr-color-brand`/`-brand-quiet`. Upstream aliases are `--track-width`,
`--track-color`, `--indicator-color`, and `--speed`.
