---
title: Spinner
description: An indicator that can be used to show a loading state.
---

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/item"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ SpinnerDemo() {
	<div class="flex w-full max-w-xs flex-col gap-4 [--radius:1rem]">
		@item.Item(item.Props{Variant: item.VariantMuted}) {
			@item.Media() {
				@spinner.Spinner()
			}
			@item.Content() {
				@item.Title(item.TitleProps{Class: "line-clamp-1"}) {
					Processing payment...
				}
			}
			@item.Content(item.ContentProps{Class: "flex-none justify-end"}) {
				<span class="text-sm tabular-nums">$100.00</span>
			}
		}
	</div>
}
```

## Installation

<CodeTabs>

<TabsList>
  <TabsTrigger value="cli">Command</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
shadcn-templ add spinner
```

</TabsContent>

<TabsContent value="manual">

<Steps className="mb-0 pt-2">

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="spinner" title="components/spinner/spinner.templ" />

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</CodeTabs>

## Usage

```go showLineNumbers
import "github.com/axadrn/shadcn-templ/v2/components/spinner"
```

```templ showLineNumbers
@spinner.Spinner()
```

## Customization

You can replace the default spinner icon with any other icon by editing the `Spinner` component.

```templ
package examples

import "github.com/axadrn/shadcn-templ/v2/components/icon"

// The demo's own Spinner: the default icon swapped for icon.Loader, the
// pendant of editing the component like the docs describe.
templ spinnerCustomSpinner() {
	@icon.Loader(icon.Props{
		Class: "size-4 animate-spin",
		Attributes: templ.Attributes{
			"data-slot":  "spinner",
			"role":       "status",
			"aria-label": "Loading",
		},
	})
}

templ SpinnerCustom() {
	<div class="flex items-center gap-4">
		@spinnerCustomSpinner()
	</div>
}
```

```templ showLineNumbers title="components/spinner/spinner.templ"
templ Spinner(props ...Props) {
	{{ var p Props }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	@icon.Loader(icon.Props{
		Class: utils.CN("size-4 animate-spin", p.Class),
		Attributes: templ.Attributes{
			"role":       "status",
			"aria-label": "Loading",
		},
	})
}
```

## Size

Use the `size-*` utility class to change the size of the spinner.

```templ
package examples

import "github.com/axadrn/shadcn-templ/v2/components/spinner"

templ SpinnerSize() {
	<div class="flex items-center gap-6">
		@spinner.Spinner(spinner.Props{Class: "size-3"})
		@spinner.Spinner(spinner.Props{Class: "size-4"})
		@spinner.Spinner(spinner.Props{Class: "size-6"})
		@spinner.Spinner(spinner.Props{Class: "size-8"})
	</div>
}
```

## Button

Add a spinner to a button to indicate a loading state. Place the `@spinner.Spinner()` before the label with `data-icon="inline-start"` for a start position, or after the label with `data-icon="inline-end"` for an end position.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ SpinnerButton() {
	<div class="flex flex-col items-center gap-4">
		@button.Button(button.Props{
			Disabled: true,
			Size:     button.SizeSm,
		}) {
			@spinner.Spinner(spinner.Props{
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Loading...
		}
		@button.Button(button.Props{
			Variant:  button.VariantOutline,
			Disabled: true,
			Size:     button.SizeSm,
		}) {
			@spinner.Spinner(spinner.Props{
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Please wait
		}
		@button.Button(button.Props{
			Variant:  button.VariantSecondary,
			Disabled: true,
			Size:     button.SizeSm,
		}) {
			@spinner.Spinner(spinner.Props{
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Processing
		}
	</div>
}
```

## Badge

Add a spinner to a badge to indicate a loading state. Place the `@spinner.Spinner()` before the label with `data-icon="inline-start"` for a start position, or after the label with `data-icon="inline-end"` for an end position.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/badge"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ SpinnerBadge() {
	<div class="flex items-center gap-4 [--radius:1.2rem]">
		@badge.Badge() {
			@spinner.Spinner(spinner.Props{
				Class:      "size-3",
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Syncing
		}
		@badge.Badge(badge.Props{Variant: badge.VariantSecondary}) {
			@spinner.Spinner(spinner.Props{
				Class:      "size-3",
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Updating
		}
		@badge.Badge(badge.Props{Variant: badge.VariantOutline}) {
			@spinner.Spinner(spinner.Props{
				Class:      "size-3",
				Attributes: templ.Attributes{"data-icon": "inline-start"},
			})
			Processing
		}
	</div>
}
```

## Input Group

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/inputgroup"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ SpinnerInputGroup() {
	<div class="flex w-full max-w-md flex-col gap-4">
		@inputgroup.InputGroup() {
			@inputgroup.Input(inputgroup.InputProps{
				Placeholder: "Send a message...",
				Disabled:    true,
			})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignInlineEnd}) {
				@spinner.Spinner()
			}
		}
		@inputgroup.InputGroup() {
			@inputgroup.Textarea(inputgroup.TextareaProps{
				Placeholder: "Send a message...",
				Disabled:    true,
			})
			@inputgroup.Addon(inputgroup.AddonProps{Align: inputgroup.AlignBlockEnd}) {
				@spinner.Spinner()
				Validating...
				@inputgroup.Button(inputgroup.ButtonProps{
					Variant: button.VariantDefault,
					Class:   "ml-auto",
				}) {
					@icon.ArrowUp()
					<span class="sr-only">Send</span>
				}
			}
		}
	</div>
}
```

## Empty

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/empty"
	"github.com/axadrn/shadcn-templ/v2/components/spinner"
)

templ SpinnerEmpty() {
	@empty.Empty(empty.Props{Class: "w-full"}) {
		@empty.Header() {
			@empty.Media(empty.MediaProps{Variant: empty.MediaVariantIcon}) {
				@spinner.Spinner()
			}
			@empty.Title() {
				Processing your request
			}
			@empty.Description() {
				Please wait while we process your request. Do not refresh the page.
			}
		}
		@empty.Content() {
			@button.Button(button.Props{
				Variant: button.VariantOutline,
				Size:    button.SizeSm,
			}) {
				Cancel
			}
		}
	}
}
```

## API Reference

### Spinner

The `Spinner` component renders a spinning loader icon with `role="status"`.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |
