Processing payment...
$100.00
<script lang="ts">
import { Spinner } from "$lib/components/ui/spinner/index.js";
import * as Item from "$lib/components/ui/item/index.js";
</script>
<div class="flex w-full max-w-xs flex-col gap-4 [--radius:1rem]">
<Item.Root variant="muted">
<Item.Media>
<Spinner />
</Item.Media>
<Item.Content>
<Item.Title class="line-clamp-1">Processing payment...</Item.Title>
</Item.Content>
<Item.Content class="flex-none justify-end">
<span class="text-sm tabular-nums">$100.00</span>
</Item.Content>
</Item.Root>
</div> Installation
Install @lucide/svelte:
Copy and paste the following code into your project.
Usage
<script lang="ts">
import { Spinner } from "$lib/components/ui/spinner/index.js";
</script> <Spinner /> Customization
You can replace the default spinner icon with any other icon by editing the Spinner component.
<script lang="ts">
import { cn } from "$lib/utils.js";
import LoaderIcon from "@lucide/svelte/icons/loader";
import type { ComponentProps } from "svelte";
type Props = ComponentProps<typeof LoaderIcon>;
let { class: className, ...restProps }: Props = $props();
</script>
<LoaderIcon
role="status"
aria-label="Loading"
class={cn("size-4 animate-spin", className)}
{...restProps}
/> Examples
Size
Use the size-* utility class to change the size of the spinner.
<script lang="ts">
import { Spinner } from "$lib/components/ui/spinner/index.js";
</script>
<div class="flex items-center gap-6">
<Spinner class="size-3" />
<Spinner class="size-4" />
<Spinner class="size-6" />
<Spinner class="size-8" />
</div> Color
Use the text-* utility class to change the color of the spinner.
<script lang="ts">
import { Spinner } from "$lib/components/ui/spinner/index.js";
</script>
<div class="flex items-center gap-6">
<Spinner class="size-6 text-red-500" />
<Spinner class="size-6 text-green-500" />
<Spinner class="size-6 text-blue-500" />
<Spinner class="size-6 text-yellow-500" />
<Spinner class="size-6 text-purple-500" />
</div> Button
Add a spinner to a button to indicate a loading state. The <Button /> will handle the spacing between the spinner and the text.
<script lang="ts">
import { Button } from "$lib/components/ui/button/index.js";
import { Spinner } from "$lib/components/ui/spinner/index.js";
</script>
<div class="flex flex-col items-center gap-4">
<Button disabled size="sm">
<Spinner />
Loading...
</Button>
<Button variant="outline" disabled size="sm">
<Spinner />
Please wait
</Button>
<Button variant="secondary" disabled size="sm">
<Spinner />
Processing
</Button>
</div> Badge
You can also use a spinner inside a badge.
Syncing Updating Loading
<script lang="ts">
import { Badge } from "$lib/components/ui/badge/index.js";
import { Spinner } from "$lib/components/ui/spinner/index.js";
</script>
<div class="flex items-center gap-2">
<Badge>
<Spinner />
Syncing
</Badge>
<Badge variant="secondary">
<Spinner />
Updating
</Badge>
<Badge variant="outline">
<Spinner />
Loading
</Badge>
</div> Input Group
Input Group can have spinners inside <InputGroup.Addon>.
Validating...
<script lang="ts">
import * as InputGroup from "$lib/components/ui/input-group/index.js";
import { Spinner } from "$lib/components/ui/spinner/index.js";
import ArrowUpIcon from "@lucide/svelte/icons/arrow-up";
</script>
<div class="flex w-full max-w-md flex-col gap-4">
<InputGroup.Root>
<InputGroup.Input placeholder="Send a message..." disabled />
<InputGroup.Addon align="inline-end">
<Spinner />
</InputGroup.Addon>
</InputGroup.Root>
<InputGroup.Root>
<InputGroup.Textarea placeholder="Send a message..." disabled />
<InputGroup.Addon align="block-end">
<Spinner /> Validating...
<InputGroup.Button class="ms-auto" variant="default">
<ArrowUpIcon />
<span class="sr-only">Send</span>
</InputGroup.Button>
</InputGroup.Addon>
</InputGroup.Root>
</div> Empty
Processing your request
Please wait while we process your request. Do not refresh the page.
<script lang="ts">
import * as Empty from "$lib/components/ui/empty/index.js";
import { Spinner } from "$lib/components/ui/spinner/index.js";
import { Button } from "$lib/components/ui/button/index.js";
</script>
<Empty.Root class="w-full border md:p-6">
<Empty.Header>
<Empty.Media variant="icon">
<Spinner />
</Empty.Media>
<Empty.Title>Processing your request</Empty.Title>
<Empty.Description>
Please wait while we process your request. Do not refresh the page.
</Empty.Description>
</Empty.Header>
<Empty.Content>
<Button variant="outline" size="sm">Cancel</Button>
</Empty.Content>
</Empty.Root> Item
Use the spinner inside <Item.Media> to indicate a loading state.
Downloading...
129 MB / 1000 MB
<script lang="ts">
import * as Item from "$lib/components/ui/item/index.js";
import { Spinner } from "$lib/components/ui/spinner/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import { Progress } from "$lib/components/ui/progress/index.js";
</script>
<div class="flex w-full max-w-md flex-col gap-4 [--radius:1rem]">
<Item.Root variant="outline">
<Item.Media variant="icon">
<Spinner />
</Item.Media>
<Item.Content>
<Item.Title>Downloading...</Item.Title>
<Item.Description>129 MB / 1000 MB</Item.Description>
</Item.Content>
<Item.Actions class="hidden sm:flex">
<Button variant="outline" size="sm">Cancel</Button>
</Item.Actions>
<Item.Footer>
<Progress value={75} />
</Item.Footer>
</Item.Root>
</div>