| title | Button with Loading States |
|---|---|
| description | Guide for implementing loading states in buttons using the Spinner component. |
Use the shadcn-vue Spinner component inside buttons to show loading states during async operations.
services/frontend/src/components/ui/button/
├── Button.vue # Standard shadcn-vue button
└── index.ts # Button variants and exports
services/frontend/src/components/ui/spinner/
├── Spinner.vue # Animated loading spinner
└── index.ts # Spinner exports
Import both Button and Spinner, then conditionally render the Spinner inside the button:
<script setup lang="ts">
import { ref } from 'vue'
import { Button } from '@/components/ui/button'
import { Spinner } from '@/components/ui/spinner'
import { toast } from 'vue-sonner'
const isSubmitting = ref(false)
const handleSubmit = async () => {
isSubmitting.value = true
try {
await saveData()
toast.success('Saved successfully')
} catch (error) {
toast.error('Save failed', { description: error.message })
} finally {
isSubmitting.value = false
}
}
</script>
<template>
<Button
:disabled="isSubmitting"
@click="handleSubmit"
>
<Spinner v-if="isSubmitting" class="mr-2" />
Save Changes
</Button>
</template>The loading button pattern consists of three parts:
- Disable the button - Add
:disabled="isLoading"to prevent double clicks - Show the spinner - Add
<Spinner v-if="isLoading" class="mr-2" />before the text - Keep the text visible - The button text remains visible during loading
The Spinner component accepts a class prop for styling:
<!-- Smaller spinner -->
<Spinner v-if="isLoading" class="mr-2 size-3" />
<!-- Different color -->
<Spinner v-if="isLoading" class="mr-2 text-white" /><Button :disabled="isSubmitting" @click="handleSubmit">
<Spinner v-if="isSubmitting" class="mr-2" />
{{ isSubmitting ? 'Saving...' : 'Save Changes' }}
</Button><Button
variant="destructive"
:disabled="isDeleting"
@click="handleDelete"
>
<Spinner v-if="isDeleting" class="mr-2" />
Delete
</Button><Button
:disabled="!isFormValid || isSubmitting"
@click="handleSubmit"
>
<Spinner v-if="isSubmitting" class="mr-2" />
Submit
</Button>- UI Design System - Overall design patterns
- Global Sonner Toast System - Toast notifications