Skip to content
LuoForge/Tungsten
Components/Spinner·Experimental

Spinner

since v14.1.0

Indeterminate loading indicator. Two modes:

• Inline (<Spinner aria-label="Loading" />) — sits in flow.

• Wrapper (<Spinner spinning>{children}</Spinner>) — dims + inerts the

children and overlays a centered spinner, preserving their footprint

(no reflow, local stacking only).

currentColor indicator (defaults to ink). Never brand. Reduced-motion users

get the static track ring (via {@link SpinnerIcon}) plus the text affordance.

Install

Add the package and import the component.

pnpm add @hey-mike/tungsten
pnpm add @hey-mike/tungsten
import { Spinner } from '@hey-mike/tungsten';
import { Spinner } from '@hey-mike/tungsten';

Preview

Same fixtures used by the visual-regression suite.

Usage

apps/docs/app/snapshots/spinner/page.tsx

import { Spinner } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';

export default function SpinnerSnapshot() {
  return (
    <VariantGrid
      title="Spinner"
      hero={<Spinner size="lg" tip="Loading" />}
      variants={[
        {
          label: 'sizes',
          node: (
            <div className="flex items-center gap-6">
              <Spinner size="sm" aria-label="Loading" />
              <Spinner size="md" aria-label="Loading" />
              <Spinner size="lg" aria-label="Loading" />
            </div>
          ),
        },
        { label: 'with tip', node: <Spinner tip="Saving…" /> },
        {
          label: 'wrapper',
          node: (
            <div className="w-64">
              <Spinner tip="Loading" spinning>
                <div className="bg-surface-2 border-stroke text-ink-2 rounded-md border p-4 text-sm">
                  Content being loaded — dimmed and inert while the spinner overlays it.
                </div>
              </Spinner>
            </div>
          ),
        },
      ]}
    />
  );
}
import { Spinner } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';

export default function SpinnerSnapshot() {
  return (
    <VariantGrid
      title="Spinner"
      hero={<Spinner size="lg" tip="Loading" />}
      variants={[
        {
          label: 'sizes',
          node: (
            <div className="flex items-center gap-6">
              <Spinner size="sm" aria-label="Loading" />
              <Spinner size="md" aria-label="Loading" />
              <Spinner size="lg" aria-label="Loading" />
            </div>
          ),
        },
        { label: 'with tip', node: <Spinner tip="Saving…" /> },
        {
          label: 'wrapper',
          node: (
            <div className="w-64">
              <Spinner tip="Loading" spinning>
                <div className="bg-surface-2 border-stroke text-ink-2 rounded-md border p-4 text-sm">
                  Content being loaded — dimmed and inert while the spinner overlays it.
                </div>
              </Spinner>
            </div>
          ),
        },
      ]}
    />
  );
}

Props

Surface specific to <Spinner />.

PropTypeDefaultDescription
spinningbooleanWhether the spinner is active. Default true.
size"sm" | "md" | "lg"Indicator size. Default 'md'.
delaynumberDelay in ms before showing the spinner — skips the flash on fast loads. Default 0.
childrenReactNodeWrap content: dims + makes it inert and overlays the spinner while spinning.
classNamestring
tipReactNode
aria-labelstring
aria-labelledbystring

Source