RadCN
Feedbackreadycomponentready

Spinner

An accessible loading status indicator for standalone feedback and composed loading states.

Importimport { Spinner } from 'radcn/spinner'
Preview

Live package example

Render standalone, sized, colored, button, badge, input-group, empty, item, progress, and custom presentation examples without React or icon-package dependencies.

Example Parity

Render standalone, sized, colored, button, badge, input-group, empty, item, progress, and custom presentation examples without React or icon-package dependencies.

Preview
Basic
Size
Color
Syncing Updating Processing
Processing your request
Please wait while we process your request.
Processing payment...
$100.00
Downloading...

129 MB / 1000 MB

Custom
import { Badge } from 'radcn/badge'
import { Button } from 'radcn/button'
import { Empty, EmptyContent, EmptyHeader, EmptyMedia, EmptyTitle } from 'radcn/empty'
import { InputGroup, InputGroupAddon, InputGroupInput } from 'radcn/input-group'
import { Item, ItemContent, ItemFooter, ItemGroup, ItemMedia, ItemTitle } from 'radcn/item'
import { Progress } from 'radcn/progress'
import { Spinner } from 'radcn/spinner'

export function SpinnerPreview() {
  return (
    <div class="spinner-preview">
      <Spinner />
      <Spinner style="width:1.5rem;height:1.5rem;color:#2563eb" />
      <Button disabled size="sm"><Spinner ariaLabel="Loading" /> Loading...</Button>
      <Badge variant="outline"><Spinner ariaLabel="Processing" /> Processing</Badge>
      <InputGroup disabled><InputGroupInput disabled placeholder="Searching..." /><InputGroupAddon align="inline-end"><Spinner /></InputGroupAddon></InputGroup>
      <Empty>
        <EmptyHeader><EmptyMedia variant="icon"><Spinner /></EmptyMedia><EmptyTitle>Processing your request</EmptyTitle></EmptyHeader>
        <EmptyContent><Button size="sm" variant="outline">Cancel</Button></EmptyContent>
      </Empty>
      <ItemGroup>
        <Item variant="outline">
          <ItemMedia variant="icon"><Spinner /></ItemMedia>
          <ItemContent><ItemTitle>Downloading...</ItemTitle></ItemContent>
          <ItemFooter><Progress value={75} /></ItemFooter>
        </Item>
      </ItemGroup>
    </div>
  )
}

Installation

Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.

pnpm add radcn # intended future package
import { Spinner } from 'radcn/spinner'

Theming

RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.

<html data-radcn-theme-mode="system" data-radcn-theme="dark">
  ...
</html>

Accessibility

  • Spinner renders role="status" with a default Loading accessible name.
  • Use ariaLabel when the loading state needs a more specific status name.
  • Loading text belongs beside Spinner in Button, Badge, InputGroup, Empty, and Item compositions.
  • Custom app-owned spinner replacements should preserve role="status" and an accessible name.

Customization

  • Use the class and style props (Tailwind size-* and text-* utilities, or inline width/height and color) for size and color customization.
  • Spinner track and head parts expose package classes for token-driven styling.
  • Button, Badge, InputGroup, Empty, Item, and Progress compositions keep their own public hooks and state.

Remix 3 Notes

  • Upstream lucide LoaderIcon and Loader2Icon map to RadCN package-owned SVG by default; app-owned custom icons can replace the visual glyph when needed.
  • React SVG prop spreading maps to deliberate Remix UI props, public classes, inline styles, and CSS variables.
  • Tailwind size-* and text-* utilities (or inline width/height and color via the class and style props) customize the spinner.
  • Custom spinner replacement is app-owned presentation, not a RadCN package dependency.
  • Spinner does not own Button, Badge, InputGroup, Empty, Item, Progress, form, or async state.