v1.1.1

Spinner

A loading spinner to indicate an ongoing process.

Default

Basic spinning circle indicator.

html
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-6 vt-w-6 vt-text-info-fill">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
</svg>

Sizes

Small (16px), medium (24px), large (32px), and extra-large (48px) spinners.

html
sm
md
lg
xl
<div class="vt-flex vt-flex-col vt-items-center vt-gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-4 vt-w-4 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-xs vt-text-foreground-muted">sm</span>
</div>

<div class="vt-flex vt-flex-col vt-items-center vt-gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-6 vt-w-6 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-xs vt-text-foreground-muted">md</span>
</div>

<div class="vt-flex vt-flex-col vt-items-center vt-gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-8 vt-w-8 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-xs vt-text-foreground-muted">lg</span>
</div>

<div class="vt-flex vt-flex-col vt-items-center vt-gap-2">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-12 vt-w-12 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-xs vt-text-foreground-muted">xl</span>
</div>

With Label

Spinner accompanied by a text label.

html
Loading...
Please wait while we process your request...
Loading content...
<div class="vt-flex vt-items-center vt-gap-3">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-5 vt-w-5 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-sm vt-text-foreground-muted">Loading...</span>
</div>

<div class="vt-flex vt-items-center vt-gap-3">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-5 vt-w-5 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-sm vt-text-foreground-muted">Please wait while we process your request...</span>
</div>

<div class="vt-flex vt-flex-col vt-items-center vt-gap-3 vt-py-4">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-8 vt-w-8 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <span class="vt-text-sm vt-text-foreground-muted">Loading content...</span>
</div>

Button with Spinner

Buttons showing a loading state with an embedded spinner.

html
<button disabled="" class="vt-btn vt-btn-primary vt-gap-2 vt-opacity-70 vt-cursor-not-allowed">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-4 vt-w-4">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  Loading...
</button>

<button disabled="" class="vt-btn vt-btn-secondary vt-gap-2 vt-opacity-70 vt-cursor-not-allowed">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-4 vt-w-4">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  Saving...
</button>

<button disabled="" class="vt-btn vt-btn-bordered vt-gap-2 vt-opacity-70 vt-cursor-not-allowed">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-4 vt-w-4">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  Uploading...
</button>

<button disabled="" class="vt-btn vt-btn-danger vt-gap-2 vt-opacity-70 vt-cursor-not-allowed">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-4 vt-w-4">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  Deleting...
</button>

<button class="vt-btn vt-btn-primary">
  Submit
</button>

Full Page Overlay

A spinner overlay covering the full page. Click the button to preview.

html

Loading, please wait...

(Click anywhere to dismiss)

<button class="vt-btn vt-btn-primary" onclick="document.getElementById('overlay-spinner').classList.remove('vt-hidden')">

  Show Overlay Spinner
</button>

<div id="overlay-spinner" class="vt-hidden vt-fixed vt-inset-0 vt-z-[100] vt-bg-surface-card/80 vt-flex vt-flex-col vt-items-center vt-justify-center vt-gap-4" onclick="this.classList.add('vt-hidden')">
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-loader-circle vt-animate-spin vt-h-12 vt-w-12 vt-text-info-fill">
    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
  </svg>
  <p class="vt-text-sm vt-text-foreground-muted">Loading, please wait...</p>
  <p class="vt-text-xs vt-text-foreground-muted vt-mt-2">(Click anywhere to dismiss)</p>
</div>

Guidelines

Signal an indeterminate wait when the duration is unknown; for measurable progress use a progress bar.

Loading...
Do
Pair the spinner with a label so users know what's loading.
Don't
Don't scatter multiple spinners; use one for the whole region.

API Reference

All CSS classes available for the Spinner component.

Class Type Description
vt-animate-spin Animation Applies continuous rotation animation to the spinner
vt-h-4 vt-w-4 Size Small spinner (16px)
vt-h-6 vt-w-6 Size Medium spinner (24px, default)
vt-h-8 vt-w-8 Size Large spinner (32px)
vt-h-12 vt-w-12 Size Extra-large spinner (48px)
vt-text-info-fill Color Primary spinner color
vt-text-foreground-muted Color Muted label text color
vt-opacity-70 State Reduced opacity for loading button state
vt-cursor-not-allowed State Not-allowed cursor for disabled loading buttons
vt-fixed vt-inset-0 Layout Full-page overlay positioning
vt-bg-surface-card/80 Overlay Semi-transparent surface background for overlay

Accessibility

Keyboard and screen reader support.

Feature Details
Role Use role="status" on the spinner container for screen reader announcement
Label Add aria-label="Loading" or include sr-only "Loading..." text
Hidden Hide spinner from screen readers if a separate loading announcement exists
Motion Respect prefers-reduced-motion by reducing or pausing animation