Skip to main content
Button is a key component built on top of Link and supports all link functionality including navigation, external links, and disabled states.

Basic Usage

The Button component renders an interactive button element with support for labels, icons, avatars, and loading states.
<template>
  <UButton label="Click me" />
</template>

Props

label
string
The text label to display inside the button.
color
string
default:"primary"
The color theme of the button. Supports all theme colors plus neutral.Available colors: primary, secondary, success, warning, error, info, neutral
variant
string
default:"solid"
The visual style variant of the button.Available variants:
  • solid - Filled background with contrasting text
  • outline - Border with transparent background
  • soft - Subtle background tint
  • subtle - Soft background with border
  • ghost - Minimal styling, background on hover
  • link - Text-only, underlined on hover
size
string
default:"md"
The size of the button.Available sizes: xs, sm, md, lg, xl
square
boolean
default:"false"
Render the button with equal padding on all sides. Automatically enabled when no label or default slot content is provided.
block
boolean
default:"false"
Render the button full width with centered content.
icon
string
Icon name to display. Position determined by leading or trailing prop.
leadingIcon
string
Icon name to display before the label.
trailingIcon
string
Icon name to display after the label.
leading
boolean
Show the icon before the label.
trailing
boolean
Show the icon after the label.
loading
boolean
default:"false"
Display a loading spinner. The spinner replaces the leading or trailing icon.
loadingAuto
boolean
default:"false"
Automatically set loading state based on the @click promise state. The button shows a loading state while the click handler promise is pending.
avatar
AvatarProps
Avatar configuration object. Displays an avatar before the label instead of an icon.
activeColor
string
Color to apply when the button is in an active state (e.g., active router link).
activeVariant
string
Variant to apply when the button is in an active state.
disabled
boolean
default:"false"
Disable the button interaction.
type
string
default:"button"
HTML button type attribute. Use submit for form submission.
to
string | object
Navigation target. Supports Vue Router location objects.
href
string
External link URL.
target
string
Link target attribute (e.g., _blank for new tab).
ui
object
Override component styles. Accepts partial UI configuration for customizing specific slots.
class
any
Additional CSS classes to apply to the button.

Slots

leading
slot
Custom content to display before the label. Receives { ui } as slot props.
<UButton>
  <template #leading>
    <CustomIcon />
  </template>
  Label
</UButton>
default
slot
Custom button content. Receives { ui } as slot props. When provided, the label prop is ignored.
<UButton>
  <span>Custom <strong>Content</strong></span>
</UButton>
trailing
slot
Custom content to display after the label. Receives { ui } as slot props.
<UButton>
  Label
  <template #trailing>
    <CustomBadge />
  </template>
</UButton>

Events

@click
(event: MouseEvent) => void | Promise<void>
Click event handler. Supports async functions. When used with loadingAuto, the button displays a loading state until the promise resolves.

Examples

Variants

<template>
  <UButton variant="solid" color="primary" label="Solid Button" />
</template>
The default variant with a filled background. Ideal for primary actions.

Colors

<template>
  <UButton color="primary" label="Primary" />
</template>

Sizes

<template>
  <div class="flex items-center gap-2">
    <UButton size="xs" label="XS" />
    <UButton size="sm" label="SM" />
    <UButton size="md" label="MD" />
    <UButton size="lg" label="LG" />
    <UButton size="xl" label="XL" />
  </div>
</template>

With Icons

<template>
  <UButton 
    leadingIcon="i-heroicons-plus" 
    label="Add Item" 
  />
</template>

Loading States

<script setup>
import { ref } from 'vue'

const isLoading = ref(false)

async function handleClick() {
  isLoading.value = true
  await new Promise(resolve => setTimeout(resolve, 2000))
  isLoading.value = false
}
</script>

<template>
  <UButton 
    :loading="isLoading" 
    label="Submit" 
    @click="handleClick"
  />
</template>

With Avatar

<template>
  <UButton 
    :avatar="{ src: 'https://i.pravatar.cc/300', alt: 'User' }" 
    label="Profile"
  />
</template>

Block Button

<template>
  <UButton 
    block 
    label="Full Width Button"
  />
</template>
<template>
  <UButton 
    to="/dashboard" 
    label="Go to Dashboard"
  />
</template>

Active State

<template>
  <UButton 
    to="/settings" 
    label="Settings"
    activeColor="success"
    activeVariant="solid"
  />
</template>
When the button is used as a router link and matches the current route, it applies the active color and variant.

Disabled State

<template>
  <UButton 
    disabled 
    label="Disabled Button"
  />
</template>

Custom Slots

<template>
  <UButton>
    <template #leading>
      <svg class="size-5"><!-- custom icon --></svg>
    </template>
    
    <div class="flex flex-col items-start">
      <span class="font-semibold">Multi-line</span>
      <span class="text-xs opacity-75">With description</span>
    </div>
    
    <template #trailing>
      <span class="text-xs">⌘K</span>
    </template>
  </UButton>
</template>

Theming

The Button component uses Tailwind Variants for theming. Size configuration:
  • Padding: px-2 py-1
  • Text: text-xs
  • Gap: gap-1
  • Icon size: size-4
  • Avatar size: 3xs

Accessibility

  • Buttons are keyboard accessible and can be activated with Enter or Space
  • Disabled buttons have aria-disabled attribute and reduced opacity
  • Loading state is communicated through visual spinner
  • Focus visible states with outline for keyboard navigation
  • Supports all standard link and button ARIA attributes
  • ButtonGroup - Group multiple buttons together
  • Link - Base link component
  • Icon - Icon component used in buttons
  • Avatar - Avatar component for button avatars

Build docs developers (and LLMs) love