Feedback & status

AppSpinner

A small indeterminate busy indicator, for when a skeleton would be wrong.

<app-spinner size="sm" label="Checking availability" />

<app-spinner> says “working” where there is no shape to preview — inside a small control, beside an inline status, in a compact cell. It is Bootstrap's .spinner-border, tinted by the theme.

It is deliberately the second choice for loading. For content that is about to appear, a skeleton is better; see below.

Playground

Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the spinner above it.

<app-spinner />

Basic

Two presets, or any exact pixel size. sm sits inline with text or inside a control; md stands alone in a small area.

sm and md
Give it a label when the page has more than one — “Loading” twice tells a screen reader nothing about which.
Show code
<app-spinner size="sm" label="Checking availability" />
<app-spinner />
Any pixel size
Pass a number to set the exact diameter — the spinner scales its own border to match, so it stays crisp at any size.
Show code
<app-spinner size="16" />
<app-spinner size="28" />
<app-spinner size="48" />
A busy button already has one<app-button loading="true"> renders its own spinner and disables the button. Don't compose the two by hand.
Inside a button
Use the loading attribute rather than putting a spinner in the label.
Show code
<app-button loading="true">Saving…</app-button>

Spinner vs skeleton

For content with a known shape — a table, a card, a list — a skeleton is better on both counts: it tells the reader what is coming, and the layout does not jump when the data lands.

The same wait, two ways
Left: a spinner in the middle of an empty area — the reader learns nothing and the layout will shift. Right: a placeholder in the shape of what is loading.
Show code
@* Prefer this for above-the-fold content *@
<table class="table table-ledger">
  <tbody>
    <tr>
      <td><app-skeleton width="70%" height="12px" /></td>
      <td><app-skeleton width="50%" height="12px" /></td>
    </tr>
  </tbody>
</table>

@* A spinner is right for a small, shapeless wait *@
<app-spinner size="sm" label="Checking availability" />

When to use

Use it when

  • A short, shapeless wait — a validity check, an inline recalculation.
  • The busy area is too small for a skeleton to read as anything.
  • You need a busy indicator next to a status line or in a table cell.

Reach for something else when

  • Content with a known shape is loading. → app-skeleton
  • A button is submitting. → app-button loading
  • The whole app is booting. → app-splash
  • The wait finished with nothing to show. → app-empty-state

Best practices

Do
A label that says what is happening, sized to sit inline with the thing it belongs to.
Don't
A lone spinner filling a content area: no indication of what is loading, no idea how long, and the layout will jump when the real content arrives.

Every option

The whole surface of the component, one cell per value.

size — presets and exact pixel diameters

size="sm"
size="md"
size="16"
size="24"
size="32"
size="48"
size="64"

label

(default) label="Loading"
label="Checking availability"

class passthrough

class="text-primary"
class="text-danger" size="sm"

Attributes

AttributeTypeDefaultDescription
sizesm | md | numbermdsm to sit inline with text or inside a control, or an exact pixel diameter for any other size.
labelstringLoadingAccessible name. Say what is loading when the page has more than one spinner.