A compact loading indicator with three sizes, an accessible label, and reduced-motion behavior.
import { Spinner } from "@/components/ballmac/spinner"
export default function SpinnerDemo() {
return (
<div className="flex w-full max-w-xs items-center justify-between rounded-xl border bg-card p-5 shadow-sm">
<div>
<div className="text-sm font-semibold">Saving changes</div>
<div className="mt-1 text-xs text-muted-foreground">
Your workspace will update shortly.
</div>
</div>
<Spinner size="lg" label="Saving changes" className="text-primary" />
</div>
)
}Installation
$ pnpm dlx shadcn@latest add @ballmac/spinnerInstall the dependencies.
$ pnpm add lucide-reactAdd the Ballmac items it builds on.
$ pnpm dlx shadcn@latest add @ballmac/i18nCopy the source into your project.
components/ballmac/spinner.tsx// Ballmac UI: Spinner. https://ui.ballmac.com/components/spinner // Based on shadcn/ui Spinner (MIT, Copyright (c) 2023 shadcn), adding size variants and an announced loading state. "use client" import * as React from "react" import { LoaderCircle } from "lucide-react" import { cn } from "@/lib/utils" import { useMessages } from "@/lib/ballmac/i18n" type SpinnerProps = React.ComponentProps<"span"> & { /** Size of the loading indicator. */ size?: "sm" | "default" | "lg" /** Text announced by assistive technology. */ label?: string } function Spinner({ className, size = "default", label, ...props }: SpinnerProps) { const msg = useMessages() label ??= msg("spinner.label", "Loading") return ( <span data-slot="spinner" role="status" aria-label={label} className={cn( "inline-flex items-center justify-center text-current", className, )} {...props} > <LoaderCircle aria-hidden="true" className={cn( "motion-safe:animate-spin", size === "sm" ? "size-3.5" : size === "lg" ? "size-6" : "size-4", )} /> <span className="sr-only">{label}</span> </span> ) } export { Spinner, type SpinnerProps }Update the import paths to match your project setup.
Usage
import { Spinner } from "@/components/ballmac/spinner"The full example is in the Code tab above.
Examples
States and variants
import { Spinner } from "@/components/ballmac/spinner"
export default function SpinnerStates() {
return (
<div className="flex items-center gap-6 text-primary">
<Spinner size="sm" label="Loading small item" />
<Spinner label="Loading item" />
<Spinner size="lg" label="Loading large item" />
</div>
)
}API reference
| Prop | Type | Default |
|---|---|---|
sizeSize of the loading indicator. | "sm" | "default" | "lg" | "default" |
labelText announced by assistive technology. | string | — |
Also accepts the standard attributes of its root element.
Use with AI
A compact loading indicator with three sizes, an accessible label, and reduced-motion behavior. With the shadcn MCP server set up (guide), ask your agent:
Add the Ballmac UI Spinner (@ballmac/spinner) to this project with the shadcn MCP, then use it where it fits.
Use it for
- Show a short in-progress action
- Place inside a disabled submit button
Not for
- Use progress for a measurable operation
Registry JSON: https://ui.ballmac.com/r/spinner.json
Credits
Based on shadcn/ui Spinner, adapted by Ballmac. Free to use in personal and commercial projects.
- npm
- lucide-react
- Registry
- @ballmac/i18nshadcn/utils
Pairs well with
Button
A button with six variants, three sizes, a pill shape and a built-in loading state. buttonVariants() styles links the same way.
Alert Dialog
Focus-managed confirmation for consequential actions, with a clear cancel path, optional media, and a token-based destructive action.
Alert
A semantic callout with five theme-aware tones, clear icon placement, an action row, and opt-in urgent announcements.
Banner
A page-wide announcement with semantic tones, optional action, and controlled or local dismissal.