Displays an animation to indicate a loading or processing state.
lucide-react1import { Button } from '@/components/ui/button'
2import { Spinner } from '@/components/ui/spinner'
3
4export function SpinnerDemo() {
5 return (
6 <div className="flex flex-col items-center gap-4">
7 <Button disabled>
8 <Spinner className="mr-2 size-4" />
9 Saving...
10 </Button>
11 <Button variant="error" disabled>
12 <Spinner className="mr-2 size-4" />
13 Deleting
14 </Button>
15 <Button variant="outline" disabled>
16 <Spinner className="mr-2 size-4" />
17 Submitting
18 </Button>
19 </div>
20 )
21}
22Install the following dependencies:
1import { RefreshCwIcon } from 'lucide-react'
2
3import { cn } from '@/lib/utils'
4
5export function CustomIconSpinner({ className }: { className?: string }) {
6 return (
7 <RefreshCwIcon
8 role="status"
9 aria-label="Loading"
10 className={cn('text-primary size-7 animate-spin', className)}
11 />
12 )
13}
14Adjust the spinner’s size using the size-* utility class.
1import { Button } from '@/components/ui/button'
2import { Spinner } from '@/components/ui/spinner'
3
4export function SpinnerSizeDemo() {
5 return (
6 <div className="flex flex-col items-center gap-4">
7 <Button disabled>
8 <Spinner className="mr-2 size-2" />
9 Saving...
10 </Button>
11 <Button disabled>
12 <Spinner className="mr-2 size-4" />
13 Saving...
14 </Button>
15 <Button disabled>
16 <Spinner className="mr-2 size-6" />
17 Saving...
18 </Button>
19 <Button disabled>
20 <Spinner className="mr-2 size-8" />
21 Saving...
22 </Button>
23 </div>
24 )
25}
26Adjust the spinner’s color using the text-* utility class.
1import { Button } from '@/components/ui/button'
2import { Spinner } from '@/components/ui/spinner'
3
4export function SpinnerColorDemo() {
5 return (
6 <div className="flex flex-wrap items-center gap-4">
7 <Spinner className="text-primary size-7" />
8 <Spinner className="text-secondary size-7" />
9 <Spinner className="text-danger size-7" />
10 <Spinner className="text-warning size-7" />
11 <Spinner className="text-success size-7" />
12 <Spinner className="text-gray size-7" />
13 </div>
14 )
15}
161import { Badge } from '@/components/ui/badge'
2import { Spinner } from '@/components/ui/spinner'
3
4export function SpinnerBadgeDemo() {
5 return (
6 <div className="flex flex-wrap gap-4">
7 <Badge variant="default" className="gap-1">
8 <Spinner className="size-3" />
9 Loading
10 </Badge>
11 <Badge variant="secondary" className="gap-1">
12 <Spinner className="size-3" />
13 Processing
14 </Badge>
15 <Badge variant="outline" className="gap-1">
16 <Spinner className="size-3" />
17 Syncing
18 </Badge>
19 <Badge variant="warning" className="gap-1">
20 <Spinner className="size-3" />
21 Don't refresh
22 </Badge>
23 </div>
24 )
25}
261import { Button } from '@/components/ui/button'
2import {
3 Empty,
4 EmptyContent,
5 EmptyDescription,
6 EmptyHeader,
7 EmptyMedia,
8 EmptyTitle,
9} from '@/components/ui/empty'
10import { Spinner } from '@/components/ui/spinner'
11
12export function SpinnerEmptyData() {
13 return (
14 <Empty className="w-full">
15 <EmptyHeader>
16 <EmptyMedia variant="icon">
17 <Spinner className="text-primary size-6" />
18 </EmptyMedia>
19 <EmptyTitle>Fetching data...</EmptyTitle>
20 <EmptyDescription>
21 We're loading the latest information for you. This may
22 take a few seconds.
23 </EmptyDescription>
24 </EmptyHeader>
25 <EmptyContent className="flex flex-row items-center justify-center gap-2">
26 <Button variant="outline" size="sm">
27 Refresh
28 </Button>
29 <Button variant="ghost" size="sm">
30 Go back
31 </Button>
32 </EmptyContent>
33 </Empty>
34 )
35}
36| Prop | Type | Default |
|---|---|---|
| className | string | - |