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
The text label to display inside the button.
The color theme of the button. Supports all theme colors plus neutral.Available colors: primary, secondary, success, warning, error, info, neutral
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
The size of the button.Available sizes: xs, sm, md, lg, xl
Render the button with equal padding on all sides. Automatically enabled when no label or default slot content is provided.
Render the button full width with centered content.
Icon name to display. Position determined by leading or trailing prop.
Icon name to display before the label.
Icon name to display after the label.
Show the icon before the label.
Show the icon after the label.
Display a loading spinner. The spinner replaces the leading or trailing icon.
Automatically set loading state based on the @click promise state. The button shows a loading state while the click handler promise is pending.
Avatar configuration object. Displays an avatar before the label instead of an icon.
Color to apply when the button is in an active state (e.g., active router link).
Variant to apply when the button is in an active state.
Disable the button interaction.
HTML button type attribute. Use submit for form submission.
Navigation target. Supports Vue Router location objects.
Link target attribute (e.g., _blank for new tab).
Override component styles. Accepts partial UI configuration for customizing specific slots.
Additional CSS classes to apply to the button.
Slots
Custom content to display before the label. Receives { ui } as slot props.<UButton>
<template #leading>
<CustomIcon />
</template>
Label
</UButton>
Custom button content. Receives { ui } as slot props. When provided, the label prop is ignored.<UButton>
<span>Custom <strong>Content</strong></span>
</UButton>
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
Solid
Outline
Soft
Subtle
Ghost
Link
<template>
<UButton variant="solid" color="primary" label="Solid Button" />
</template>
The default variant with a filled background. Ideal for primary actions.<template>
<UButton variant="outline" color="primary" label="Outline Button" />
</template>
Border-only style with transparent background. Good for secondary actions.<template>
<UButton variant="soft" color="primary" label="Soft Button" />
</template>
Subtle background tint. Perfect for tertiary actions.<template>
<UButton variant="subtle" color="primary" label="Subtle Button" />
</template>
Combines soft background with a border. Balances prominence and subtlety.<template>
<UButton variant="ghost" color="primary" label="Ghost Button" />
</template>
Minimal styling with background appearing on hover. Great for toolbars.<template>
<UButton variant="link" color="primary" label="Link Button" />
</template>
Text-only appearance like a hyperlink. Use for inline actions.
Colors
Primary
Secondary
Success
Warning
Error
Neutral
<template>
<UButton color="primary" label="Primary" />
</template>
<template>
<UButton color="secondary" label="Secondary" />
</template>
<template>
<UButton color="success" label="Success" />
</template>
<template>
<UButton color="warning" label="Warning" />
</template>
<template>
<UButton color="error" label="Error" />
</template>
<template>
<UButton color="neutral" label="Neutral" />
</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
Leading Icon
Trailing Icon
Icon Only
<template>
<UButton
leadingIcon="i-heroicons-plus"
label="Add Item"
/>
</template>
<template>
<UButton
label="Next"
trailingIcon="i-heroicons-arrow-right"
/>
</template>
<template>
<UButton
icon="i-heroicons-cog-6-tooth"
square
/>
</template>
When only an icon is provided, the button automatically becomes square.
Loading States
Manual Loading
Auto Loading
<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>
<script setup>
async function handleSubmit() {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000))
console.log('Submitted!')
}
</script>
<template>
<UButton
loadingAuto
label="Submit"
@click="handleSubmit"
/>
</template>
The button automatically shows a loading spinner while the async click handler runs.
With Avatar
<template>
<UButton
:avatar="{ src: 'https://i.pravatar.cc/300', alt: 'User' }"
label="Profile"
/>
</template>
<template>
<UButton
block
label="Full Width Button"
/>
</template>
As Link
Internal Navigation
External Link
<template>
<UButton
to="/dashboard"
label="Go to Dashboard"
/>
</template>
<template>
<UButton
href="https://nuxt.com"
target="_blank"
label="Visit Nuxt"
trailingIcon="i-heroicons-arrow-top-right-on-square"
/>
</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
- Padding:
px-2.5 py-1.5
- Text:
text-xs
- Gap:
gap-1.5
- Icon size:
size-4
- Avatar size:
3xs
- Padding:
px-2.5 py-1.5
- Text:
text-sm
- Gap:
gap-1.5
- Icon size:
size-5
- Avatar size:
2xs
- Padding:
px-3 py-2
- Text:
text-sm
- Gap:
gap-2
- Icon size:
size-5
- Avatar size:
2xs
- Padding:
px-3 py-2
- Text:
text-base
- Gap:
gap-2
- Icon size:
size-6
- Avatar size:
xs
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