M
Marai.UI
v1.0.0-alpha.7

Spinner

An accessible loading indicator with semantic variants, configurable sizes, and token-driven colors. Renders itself by default.

Overview

MSpinner renders an accessible animated ring out of the box. Write <MSpinner /> and it produces a styled, accessible spinner immediately. Use Variant to control color intent, Size for scale, and Label for the screen-reader announcement. Pass ChildContent to use custom spinner markup (backward-compatible).

Usage

razor
@using Marai.UI.Components.MSpinner

Basic Usage

Preview
razor
@using Marai.UI.Components.MSpinner

<MSpinner />

Variants

Use Variant to control the spinner color. Color is driven by currentColor via your active theme's CSS variables.

Preview
razor
@using Marai.UI.Components.MSpinner

<div class="flex items-center gap-4">
    <MSpinner Variant="Variant.Default" Label="Default" />
    <MSpinner Variant="Variant.Primary" Label="Primary" />
    <MSpinner Variant="Variant.Secondary" Label="Secondary" />
    <MSpinner Variant="Variant.Success" Label="Success" />
    <MSpinner Variant="Variant.Destructive" Label="Destructive" />
    <MSpinner Variant="Variant.Warning" Label="Warning" />
    <MSpinner Variant="Variant.Info" Label="Info" />
    <MSpinner Variant="Variant.Muted" Label="Muted" />
</div>

Sizes

Use Size to control spinner dimensions.

Preview
razor
@using Marai.UI.Components.MSpinner

<div class="flex items-center gap-4">
    <MSpinner Size="Size.Xs" Label="Loading extra small" />
    <MSpinner Size="Size.Sm" Label="Loading small" />
    <MSpinner Size="Size.Default" Label="Loading" />
    <MSpinner Size="Size.Lg" Label="Loading large" />
    <MSpinner Size="Size.Xl" Label="Loading extra large" />
</div>

Label and Accessibility

Use Label to customize the screen-reader announcement. To show visible text alongside the spinner, add a <span> next to the component with flex layout.

Preview
Loading reports...
Processing settlement
razor
@using Marai.UI.Components.MSpinner

<div class="flex flex-col gap-4">
    <div class="inline-flex items-center gap-2">
        <MSpinner Variant="Variant.Primary" Size="Size.Sm" Label="Loading reports" />
        <span class="text-sm">Loading reports...</span>
    </div>
    <div class="inline-flex items-center gap-2">
        <MSpinner Variant="Variant.Muted" Size="Size.Sm" Label="Processing settlement" />
        <span class="text-sm text-slate-500">Processing settlement</span>
    </div>
</div>
Accessibility Notes
  • The outer element carries role="status" to announce loading state to screen readers.
  • aria-live="polite" is set by default so the announcement does not interrupt other speech.
  • Label defaults to "Loading"; override it to describe the specific operation.
  • The ring element carries aria-hidden="true" — the spinner is decorative, the label announces state.

Safe Tailwind Overrides

Use Class to add layout or visual utilities to the wrapper element.

Preview
razor
@using Marai.UI.Components.MSpinner

<div class="flex items-center gap-4">
    <MSpinner Variant="Variant.Primary" Class="opacity-60" Label="Dimmed spinner" />
    <MSpinner Variant="Variant.Success" Size="Size.Lg" Label="Large success spinner" />
    <MSpinner Variant="Variant.Primary" data-testid="loading-indicator" Label="Custom spinner" />
</div>

API Reference

Parameter Type Default Description
Variant Variant Variant.Default Controls text color, which drives the ring via currentColor.
Size Size Size.Default Ring dimensions (Xs, Sm, Default, Lg, Xl).
Label string? null Screen-reader announcement. Falls back to AriaLabel if not set.
Class string? null Additional Tailwind classes applied to the wrapper.
ChildContent RenderFragment? null Custom spinner markup. When provided, replaces the built-in ring.
Role string "status" ARIA role for the wrapper element.
AriaLive string "polite" Controls how assistive technology announces updates.
AriaLabel string? "Loading" Legacy screen-reader label. Use Label instead.
AdditionalAttributes Dictionary<string, object>? null Arbitrary HTML attributes forwarded to the wrapper.