Motion Loader

One loader component with twelve animated variants — orbit, newton cradle, pendulum, hourglass and more — all resolution independent and driven by transform and opacity only.

Open in v0

Last updated: August 13, 2026

Installation

npx smoothui-cli add motion-loader

Features

  • Twelve loaders from a single install, switched with the variant prop
  • Every variant animates transform and opacity only — no layout thrash, no paint-heavy properties
  • Resolution independent: SVG or scaled elements derived from a single size prop
  • Colour comes from currentColor by default, so a loader inherits the surrounding text colour; color overrides it
  • speed multiplier to tune the loop without touching the component
  • Announced as a live status region with a configurable label

Variants

VariantDescriptionAnimated properties
orbitA dot circling a faint track ringrotate
newton-cradleFive hanging balls, outer ones swinging in turnrotate
pendulumSingle arm swinging with an ease-in-out arcrotate
hourglassHourglass glyph flipping every half cyclerotate
morph-ringTwo counter-rotating dashed arcs with a scale pulserotate, scale
square-snakeA square travelling the four corners of a 2×2 gridx, y
cometA head dot with a fading four-dot tail sweeping the circlerotate
radarA conic sweep rotating inside a circular maskrotate
cube-flipA square flipping across both axes in perspectiverotateX, rotateY
wave-barsFive bars scaling vertically with a staggerscaleY
breathing-glowA blurred halo breathing around a solid corescale, opacity
dot-ringEight dots fading in sequence around a circleopacity

The full list is exported as MOTION_LOADER_VARIANTS:

import MotionLoader, {
  MOTION_LOADER_VARIANTS,
} from "@repo/smoothui/components/motion-loader";

<MotionLoader variant="orbit" size={40} label="Loading results" />;

Accessibility

ARIA Attributes

AttributeElementPurpose
role="status"Loader wrapperMarks the loader as a status region so assistive technologies observe it
aria-live="polite"Loader wrapperAnnounces the loading state without interrupting the user
aria-labelLoader wrapperNames the region from the label prop
sr-only text nodeInside the wrapperGives the live region announceable text content

Screen Reader

  • The loader is a labelled live region: mounting it announces the label politely, and unmounting it silences the region.
  • Give each loader a specific label ("Loading results", "Saving changes") rather than the generic default when several can appear on the same screen.
  • The loader is not focusable and adds nothing to the tab order.

Reduced Motion

This component respects prefers-reduced-motion via useReducedMotion from Motion. When reduced motion is preferred, every variant renders a single static frame — no animate or transition props are passed, so nothing loops. The wrapper still exposes role="status", aria-live="polite" and the label, so the loading state remains fully announced.

Props

Created by

Powered by

motion.dev

© 2026 SmoothUI. Built by Eduardo Calvo.