import { Spinner } from "@/components/ui/spinner";import { Surface } from "@/components/ui/surface";
export function SpinnerDemo() { return ( <Surface className="flex w-full max-w-sm items-center gap-3 rounded-3xl p-6"> <Spinner /> <div className="flex min-w-0 flex-1 flex-col"> <span className="truncate font-medium text-base"> Processing payment... </span> <span className="text-muted-foreground text-sm">Please wait</span> </div> <span className="text-base tabular-nums">$100.00</span> </Surface> );}pnpm dlx shadcn@latest add @herocn/spinnerimport { Spinner } from "@/components/ui/spinner"<Spinner />Use the variant prop to match the spinner color to your status or intent.
import { Spinner } from "@/components/ui/spinner";
export function SpinnerVariants() { return ( <div className="flex flex-wrap items-center gap-6"> <Spinner variant="default" /> <Spinner variant="primary" /> <Spinner variant="success" /> <Spinner variant="warning" /> <Spinner variant="destructive" /> </div> );}Use the size prop from the HeroCN spinner (sm, default, lg, xl).
import { Spinner } from "@/components/ui/spinner";
export function SpinnerSizes() { return ( <div className="flex items-center gap-6"> <Spinner size="sm" /> <Spinner size="default" /> <Spinner size="lg" /> <Spinner size="xl" /> </div> );}Add a spinner to a button to indicate a loading state. Place the spinner before
the label with data-icon="inline-start" or after it with
data-icon="inline-end".
import { Button } from "@/components/ui/button";import { Spinner } from "@/components/ui/spinner";
export function SpinnerButton() { return ( <div className="flex flex-col items-center gap-4"> <Button disabled size="sm"> <Spinner data-icon="inline-start" size="sm" /> Loading... </Button> <Button variant="outline" disabled size="sm"> Please wait <Spinner data-icon="inline-end" size="sm" /> </Button> <Button variant="secondary" disabled size="sm"> <Spinner data-icon="inline-start" size="sm" /> Processing </Button> </div> );}Add a spinner to a badge to indicate background activity.
import { Badge } from "@/components/ui/badge";import { Spinner } from "@/components/ui/spinner";
export function SpinnerBadge() { return ( <div className="flex items-center gap-4"> <Badge> <Spinner data-icon="inline-start" size="sm" /> Syncing </Badge> <Badge variant="primary"> Updating <Spinner data-icon="inline-end" size="sm" /> </Badge> <Badge variant="warning"> <Spinner data-icon="inline-start" size="sm" /> Processing </Badge> </div> );}Use a spinner in input addons to indicate async validation or processing.
import { ArrowUpIcon } from "lucide-react";
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupTextarea,} from "@/components/ui/input-group";import { Spinner } from "@/components/ui/spinner";
export function SpinnerInputGroup() { return ( <div className="flex w-full max-w-md flex-col gap-4"> <InputGroup> <InputGroupInput placeholder="Send a message..." disabled /> <InputGroupAddon align="inline-end"> <Spinner size="sm" /> </InputGroupAddon> </InputGroup> <InputGroup> <InputGroupTextarea placeholder="Send a message..." disabled /> <InputGroupAddon align="block-end"> <Spinner size="sm" /> Validating... <InputGroupButton disabled className="ml-auto" variant="default"> <ArrowUpIcon /> <span className="sr-only">Send</span> </InputGroupButton> </InputGroupAddon> </InputGroup> </div> );}Use a spinner in empty states when data is loading.
import { Button } from "@/components/ui/button";import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,} from "@/components/ui/empty";import { Spinner } from "@/components/ui/spinner";
export function SpinnerEmpty() { return ( <Empty className="w-full"> <EmptyHeader> <EmptyMedia variant="icon"> <Spinner /> </EmptyMedia> <EmptyTitle>Processing your request</EmptyTitle> <EmptyDescription> Please wait while we process your request. Do not refresh the page. </EmptyDescription> </EmptyHeader> <EmptyContent> <Button variant="outline" size="sm"> Cancel </Button> </EmptyContent> </Empty> );}"use client";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Spinner } from "@/components/ui/spinner";import { Surface } from "@/components/ui/surface";
const translations: Translations = { en: { dir: "ltr", values: { title: "Processing payment...", amount: "$100.00", }, }, ar: { dir: "rtl", values: { title: "جاري معالجة الدفع...", amount: "١٠٠.٠٠ دولار", }, }, he: { dir: "rtl", values: { title: "מעבד תשלום...", amount: "$100.00", }, },};
export function SpinnerRtl() { const { dir, language, t } = useTranslation(translations, "ar");
return ( <Surface className="flex w-full max-w-sm items-center gap-3 rounded-3xl p-6" lang={language} dir={dir} > <Spinner /> <div className="flex min-w-0 flex-1 flex-col"> <span className="truncate font-medium text-sm">{t.title}</span> </div> <span className="text-sm tabular-nums">{t.amount}</span> </Surface> );}The Spinner component accepts all native SVG props plus the following:
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "primary" | "destructive" | "success" | "warning" | "default" |
Controls the spinner color. | ||
| size | "sm" | "default" | "lg" | "xl" | "default" |
Controls the spinner size. | ||
| className | string | — |
Adds custom classes to the underlying SVG element. | ||