Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
Loading content…
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
export const SpinnerDemo = () => (
<div className="flex flex-col gap-8">
{/* Sizes */}
<div className="flex items-center gap-4">
<Spinner size="sm" />
<Spinner size="default" />
<Spinner size="lg" />
<Spinner size="xl" />
</div>
{/* Colors via text color */}
<div className="flex items-center gap-4">
<Spinner className="text-primary" />
<Spinner className="text-destructive" />
<Spinner className="text-muted-foreground" />
<Spinner className="text-green-500" />
</div>
{/* In a button */}
<div className="flex flex-wrap items-center gap-3">
<Button disabled>
<Spinner size="sm" />
Saving…
</Button>
<Button variant="outline" disabled>
<Spinner size="sm" />
Loading
</Button>
<Button variant="ghost" disabled>
<Spinner size="sm" />
Please wait
</Button>
</div>
{/* Full-page overlay pattern */}
<div className="bg-background relative flex h-28 items-center justify-center rounded-lg border">
<div className="text-muted-foreground flex flex-col items-center gap-2">
<Spinner size="lg" className="text-primary" />
<span className="text-sm">Loading content…</span>
</div>
</div>
</div>
);Sizes
<Spinner size="sm" /> {/* 16px */}
<Spinner size="default" /> {/* 20px */}
<Spinner size="lg" /> {/* 24px */}
<Spinner size="xl" /> {/* 32px */}Color
Spinner inherits currentColor — control it with any Tailwind text color class.
<Spinner className="text-primary" />
<Spinner className="text-destructive" />
<Spinner className="text-muted-foreground" />In a button
Place Spinner before the label in a disabled button while an action is in progress.
<Button disabled>
<Spinner size="sm" />
Saving…
</Button>Accessibility
Spinner renders as role="status" with aria-label. Override the label to describe the specific operation.
<Spinner label="Uploading file…" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "default" | "lg" | "xl" | "default" | Controls SVG dimensions |
label | string | "Loading…" | Accessible label (aria-label) |
className | string | — | Pass text color or additional overrides |
Usage
import { Spinner } from "@/components/ui/spinner";
<Spinner />
<Spinner size="lg" className="text-primary" />Specs
# Mint — Spinner Specs
## Component
- name: spinner
- file: registry/mint/spinner.tsx
- installs to: components/ui/spinner.tsx
- dependencies: class-variance-authority
- registryDependencies: none
## What is it
An animated SVG loading indicator that conveys an in-progress state. Use it
inside buttons, overlays, or inline next to text when an async operation is
running. Prefer Spinner over a skeleton when the wait is short and layout is
already established; do not use it as a page-level progress indicator for
long operations where a progress bar would give better feedback.
## Visual identity
Colorless by design — inherits currentColor so it adapts to any palette.
Two-layer SVG: a full-circle track at opacity-25 and a ~75° arc at opacity-75
spin continuously. The result is clean and unobtrusive on any background.
## Design tokens
No design tokens consumed directly. Color is resolved at runtime via
currentColor — set it with any Tailwind text-* utility (e.g. text-primary,
text-muted-foreground, text-destructive).
## Variants
- sm → size-4 (16px). Use inside compact controls or tight layouts.
- default → size-5 (20px). General-purpose inline loading indicator.
- lg → size-6 (24px). Standalone indicators with more breathing room.
- xl → size-8 (32px). Prominent standalone states, e.g. card loading.
## States
- spinning: always active — animate-spin runs unconditionally on mount
## Conventions
- Color: pass a Tailwind text-* class via className to tint the spinner
- In buttons: place Spinner before the label inside a disabled Button while an action is pending
- Accessible label: aria-label defaults to "Loading…" — override with the label prop to describe the specific operation (e.g. label="Uploading file…")
- Sub-components expose data-slot="spinner" for CSS targeting
- No sounds / haptic: this component does not accept a sounds or haptic propInstallation
$ npx shadcn add \https://gin-design.vercel.app/spinner