Spinner
Continuous animate-spin on the Loader2 glyph. Sized through class utilities; inherits currentColor so it tints with the surrounding text.
Usage
spinner.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
Inline with a button
spinner-button.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
Sizes
Use Tailwind size utilities. The default is size-4; scale up as needed.
spinner-sizes.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
Colors
Spinner inherits currentColor — apply any text color token to tint it.
spinner-colors.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
In Badge
Compose a processing pill by placing a Spinner inside a Badge.
Processing Syncing
spinner-badge.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
In Input Group
Place a Spinner in an InputGroup.Addon to signal a loading state on the field.
spinner-input-group.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
In Empty state
Drop a Spinner into an Empty placeholder while content is loading.
Loading results
Hang tight — fetching your data.
spinner-empty.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
In Item
Use a Spinner as Item leading media to signal that a row is processing.
Uploading report.pdf
34% — please wait
spinner-item.svelte
<script lang="ts">
import { cn } from '$lib/utils.js';
import { Icon } from '$lib/components/ui/icon';
import type { SVGAttributes } from 'svelte/elements';
let {
class: className,
role = 'status',
// we add name, color, and stroke for compatibility with different icon libraries props
name,
color,
stroke,
'aria-label': ariaLabel = 'Loading',
...restProps
}: SVGAttributes<SVGSVGElement> = $props();
</script>
<Icon
data-slot="spinner"
name="loader-4-line"
{role}
label={ariaLabel === null ? undefined : ariaLabel}
size="1rem"
class={cn('size-4 animate-spin', className)}
{...restProps as Record<string, unknown>}
/>
API reference
Inherits native SVGAttributes via spread. Renders as the Remix `loader-4-line` icon with animate-spin.
| Prop | Type | Default | Description |
|---|---|---|---|
string | — | Size and color overrides. Default size is size-4 and stroke follows currentColor. | |
string | 'Loading' | Exposed to assistive tech. Override when the spinner means something specific. | |
string | 'status' | ARIA role. Changes the announced semantics for screen readers. |