Getting Started
Components52
- Accordion
- Alert
- Alert Dialog
- Attachment
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Checkbox
- Collapsible
- Command
- Context Menu
- Data Table
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Pagination
- Popover
- Progress
- Questionnaire
- Radio Group
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
Processing payment...
$100.00
import { Item, ItemContent, ItemMedia, ItemTitle } from "@/components/ui/item"
import { Spinner } from "@/components/ui/spinner"
export function SpinnerDemo() {
return (
<div className="flex w-full max-w-xs flex-col gap-4">
<Item variant="muted">
<ItemMedia>
<Spinner />
</ItemMedia>
<ItemContent>
<ItemTitle className="line-clamp-1">Processing payment...</ItemTitle>
</ItemContent>
<ItemContent className="flex-none justify-end">
<span className="text-sm text-muted-foreground tabular-nums">
$100.00
</span>
</ItemContent>
</Item>
</div>
)
}Installation#
pnpm dlx shadcn@latest add https://ui.ikramhasan.com/r/spinner.json
Usage#
import { Spinner } from "@/components/ui/spinner"<Spinner />Eight spokes, each a step brighter, turn in eight ticks. Reduced motion halves the speed rather than stopping it, since the spinner is the only sign that work is happening.
Examples#
Size#
Use the size-* utilities to change the size of the spinner.
import { Spinner } from "@/components/ui/spinner"
export function SpinnerSizes() {
return (
<div className="flex items-center gap-6">
<Spinner className="size-3" />
<Spinner className="size-4" />
<Spinner className="size-6" />
<Spinner className="size-8" />
</div>
)
}Color#
The spinner draws in currentColor. Use text-* utilities to change it.
import { Spinner } from "@/components/ui/spinner"
export function SpinnerColor() {
return (
<div className="flex items-center gap-6">
<Spinner className="size-6 text-muted-foreground" />
<Spinner className="size-6 text-primary" />
<Spinner className="size-6 text-success" />
<Spinner className="size-6 text-destructive" />
</div>
)
}Button#
Add data-icon="inline-start" or data-icon="inline-end" to place a spinner in a button.
import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"
export function SpinnerButton() {
return (
<div className="flex flex-wrap items-center justify-center gap-2">
<Button disabled>
<Spinner data-icon="inline-start" />
Loading...
</Button>
<Button variant="secondary" disabled>
<Spinner data-icon="inline-start" />
Please wait
</Button>
<Button variant="outline" disabled>
<Spinner data-icon="inline-start" />
Processing
</Button>
</div>
)
}Badge#
SyncingUpdatingProcessing
import { Badge } from "@/components/ui/badge"
import { Spinner } from "@/components/ui/spinner"
export function SpinnerBadge() {
return (
<div className="flex items-center gap-2">
<Badge>
<Spinner data-icon="inline-start" />
Syncing
</Badge>
<Badge variant="secondary">
<Spinner data-icon="inline-start" />
Updating
</Badge>
<Badge variant="outline">
<Spinner data-icon="inline-start" />
Processing
</Badge>
</div>
)
}Input Group#
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group"
import { Spinner } from "@/components/ui/spinner"
export function SpinnerInputGroup() {
return (
<InputGroup className="max-w-xs">
<InputGroupInput
placeholder="Searching..."
aria-label="Search"
disabled
/>
<InputGroupAddon align="inline-end">
<Spinner />
</InputGroupAddon>
</InputGroup>
)
}API Reference#
Spinner renders an svg with role="status" and aria-label="Loading", and accepts all of its props.