# Loading

## Overview

The loading component presents an indeterminate activity indicator while an action or content surface is waiting to finish.

The component styles nearly any element marked with `aria-busy="true"`. Native inputs, selects, and textareas are excluded because they do not reliably render generated content.

## When to use

Use loading feedback when progress is indeterminate and the interface can communicate only that work is underway.

## When not to use

Do not use loading feedback when the interface knows how much work has completed; use a native progress element.

## Usage

For a button action that is still processing, combine `aria-busy="true"` with the native `disabled` attribute and keep a visible, action-specific label:

```html
<button disabled aria-busy="true" type="button">Saving…</button>
```

The `disabled` attribute prevents additional activation while `aria-busy="true"` exposes the loading state and adds the visual indicator.

For an inline status, apply the same state directly to the text container:

```html
<span aria-busy="true">Generating your report…</span>
```

For a card that is refreshing existing content, keep the content in place, mark the article as busy, and disable any controls that must not be activated during the update:

```html
<article aria-busy="true" aria-labelledby="busy-card-title">
  <header>
    <h3 id="busy-card-title">Quarterly update</h3>
  </header>

  <p>Content is being refreshed.</p>

  <footer>
    <button type="button" disabled>Publish</button>
  </footer>
</article>
```

The article loading treatment dims its direct child content to `48%` opacity, applies a `4px` blur, blocks pointer interaction, and centers the indicator over the existing layout. Because CSS pointer blocking does not prevent keyboard activation, native controls should use `disabled` when they must be unavailable.

The indicator inherits component defaults, but individual instances can override its color and size:

```html
<article
  aria-busy="true"
  style="--loading-color: currentColor; --loading-size: 2rem;"
></article>
```

Use this component when progress is indeterminate and the interface can only communicate that work is still underway.

Use a native `<progress>` element instead when the interface knows and can communicate how much work has completed.

The stylesheet does not determine when an operation begins or ends. The loading state remains present for as long as the rendered markup contains `aria-busy="true"` and disappears when a later render removes the attribute or changes its value.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/components.spec.js).

- LOD-001: The component supports nearly any element marked with `aria-busy="true"`, including inline text, buttons, and articles.
- LOD-002: The indicator is generated with `::before` and does not require a loading class or child element.
- LOD-003: The default indicator is a `0.75rem` circular ring built from a conic gradient and radial mask.
- LOD-004: The ring rotates continuously while its visible arc grows and shrinks to communicate indeterminate progress.
- LOD-005: Buttons use `currentColor` by default so the indicator follows the current button variant.
- LOD-006: Button indicators use the same additional trailing spacing as inline button icons.
- LOD-007: Busy disabled buttons keep disabled visual styling and use the wait cursor.
- LOD-008: Busy articles use the neutral loading color, retain at least the shared minimum control height, and center the indicator over dimmed and blurred content.
- LOD-009: Removing `aria-busy="true"` or changing its value to `false` removes the generated indicator.
- LOD-010: Reduced-motion preferences should stop both animations and leave a static partial ring visible.
- LOD-011: `--loading-color` and `--loading-size` can override the default indicator appearance without changing its state or markup.
- LOD-012: Native inputs, selects, textareas, and the root HTML element should not receive a generated loading indicator.
## Accessibility

- Use `aria-busy="true"` only while the element is waiting for an operation or content update to finish.
- Pair busy buttons with the native `disabled` attribute when they must not be activated again; `aria-busy` does not disable interaction by itself.
- Keep a visible, action-specific button label such as `Saving…` or `Deleting…` rather than using a generic label such as `Loading`.
- Keep a busy article's accessible purpose clear through its heading, `aria-label`, or `aria-labelledby`.
- Disable native controls individually when they must not be activated; for controls without native disabled behavior, expose `aria-disabled="true"` and prevent activation in application code.
- Remove the busy state when the operation finishes so assistive technologies do not continue to treat the element as incomplete.
- Treat the generated ring as decorative; the semantic loading state comes from `aria-busy`, not from the visual animation.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--loading-arc` | `<angle>` | Sets the visible spinner arc angle; change it when a static loading indicator needs a shorter or longer ring. |
| `--loading-color` | `<color>` | Sets the spinner stroke color; change it when the indicator should differ from current text color. |
| `--loading-size` | `<length>` | Sets the inline and block size of loading indicators; change it when spinners need to fit a different control or container scale. |
| `--loading-stroke` | `<length>` | Sets the spinner ring thickness; change it when the loading indicator should appear heavier or lighter. |
| `--loading-tail` | `<angle>` | Sets the spinner arc's trailing-edge position; change it to rotate a static partial ring without transforming the indicator. |

## Depends On

- `--layout-control-border-width`
