Skip to content

Loader

<Loader> is an absolutely-positioned shimmer line. Drop it inside a relative container while a longer-running operation completes — anything where the user can’t act until it’s done.

import from "@na/ui/components/Loader" ▶ Open in Storybook packages/ui/src/components/Loader.tsx

When to use

  • Page-level loading on a route transition.
  • Blocking content swap (e.g., heavy report regeneration).
  • Initial paint when even Skeleton would over-promise structure.

Don’t use Loader for: short fetches (use Skeleton), button-level mutations (use ActionButton), or progress with a known percentage (use Progress).

Default

The Loader fills its relative parent.

<div className="relative h-32 w-80 rounded-md border">
<Loader />
</div>

API

Prop Type Default Description
className string Forwarded to the wrapper. Use to override colors or position.

Design guidelines

✓ Do

  • Keep the parent `relative` so the absolute Loader covers exactly the loading region.
  • Replace with content the moment the operation resolves — don't double-flash skeleton then loader.

✗ Don't

  • Wrap your whole app in a Loader on every fetch. Pages should stream meaningful content first.
  • Use Loader where you have a percentage. That is Progress.

Accessibility

  • For meaningful loading announcements, wrap the parent region in aria-busy="true" and aria-live="polite". The Loader itself is decorative.
  • Skeleton — Structural placeholder for short fetches.
  • Progress — Determinate bar.
  • ActionButton — Button with built-in mutation states.

▶ Open Loader stories in Storybook