Skip to main content

Button

Button

Clickable button component with multiple variants, sizes, and loading states

Tags: component form action

View Demo

Buttons trigger actions and navigation. They communicate what action will occur when clicked.

Import​

<script>
  import { Button } from '@classic-homes/theme-svelte';
</script>

Basic Usage​

<Button>Click Me</Button>

Props​

Prop Type Default Description
variant 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link' 'default' Visual style variant
size 'default' | 'sm' | 'md' | 'lg' | 'icon' 'default' Size of the button
type 'button' | 'submit' | 'reset' 'button' HTML button type
href string - If provided, renders as an anchor link
disabled boolean false Disables the button
loading boolean false Shows loading spinner
loadingText string - Text to show during loading (replaces children)
class string - Additional CSS classes
onclick (e: MouseEvent) => void - Click handler

Variants​

Default​

The primary action button with solid background.

<Button variant="default">Default Button</Button>

Secondary​

Filled sage button for supporting actions such as "PDF" or "Filters": sage fill (secondary), white text, a 2px secondary-border ring, and the primary red fill on hover. Inside a Toolbar the ring takes the toolbar's light sage border automatically.

<Button variant="secondary">Secondary Button</Button>

Destructive​

For dangerous or irreversible actions like delete.

<Button variant="destructive">Delete</Button>

Outline​

Transparent button with a 2px sage (outline) border and normal foreground text; on hover it fills with the primary color and the border lightens (outline-hover). Use it for quiet actions like "Log in" or "Self Tour".

<Button variant="outline">Outline Button</Button>

Ghost​

Minimal button with no background until hovered.

<Button variant="ghost">Ghost Button</Button>

Styled as an inline text link.

<Button variant="link">Link Button</Button>

Sizes​

<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="icon">
  <svg><!-- icon --></svg>
</Button>
Size Height Padding
sm 36px (h-9) 12px (px-3)
default 40px (h-10) 16px (px-4)
md 40px (h-10) 16px (px-4)
lg 44px (h-11) 32px (px-8)
icon 40px (h-10) Square (w-10)

States​

Disabled​

<Button disabled>Disabled</Button>

Disabled buttons have reduced opacity and ignore pointer events.

Loading​

Shows a spinner and optionally replaces the text:

<Button loading>Submit</Button>
<Button loading loadingText="Saving...">Save</Button>

When loading:

  • Button is automatically disabled
  • Spinner animation appears
  • aria-busy="true" is set for accessibility

Provide an href to render as an anchor element:

<Button href="/dashboard">Go to Dashboard</Button>
<Button href="https://example.com" target="_blank">External Link</Button>

With Icons​

Add icons alongside text using the default gap styling:

<Button>
  <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
  </svg>
  Add Item
</Button>

Icon-Only Button​

Use size="icon" for square icon buttons:

<Button size="icon" variant="ghost" aria-label="Settings">
  <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      stroke-width="2"
      d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
    />
    <path
      stroke-linecap="round"
      stroke-linejoin="round"
      stroke-width="2"
      d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
    />
  </svg>
</Button>
Icon Button Accessibility

Always provide an aria-label for icon-only buttons to ensure screen reader users understand the action.

Form Submission​

Use type="submit" within forms:

<form onsubmit={handleSubmit}>
  <Button type="submit">Submit Form</Button>
</form>

Accessibility​

The Button component includes these accessibility features:

  • Full keyboard navigation (Tab, Enter, Space)
  • Visible focus ring using focus-visible
  • aria-disabled set when disabled or loading
  • aria-busy set during loading state
  • Maintains color contrast ratios

Examples​

Button Group​

<div class="flex gap-2">
  <Button variant="outline">Cancel</Button>
  <Button>Save Changes</Button>
</div>

Full Width Button​

<Button class="w-full">Full Width Button</Button>

Async Action​

<script>
  let loading = $state(false);

  async function handleSave() {
    loading = true;
    try {
      await saveData();
    } finally {
      loading = false;
    }
  }
</script>

<Button {loading} loadingText="Saving..." onclick={handleSave}>Save</Button>
  • Input - Text input for forms
  • FormField - Complete form field with validation
  • Dialog - Modal dialogs often contain action buttons
On this page