|
| 1 | +--- |
| 2 | +title: Button with Loading States |
| 3 | +description: Guide for using the enhanced Button component with built-in loading states. |
| 4 | +sidebar: Button Loading |
| 5 | +--- |
| 6 | + |
| 7 | +# Button with Loading States |
| 8 | + |
| 9 | +The Button component includes built-in loading state functionality for async operations. |
| 10 | + |
| 11 | +## Component Location |
| 12 | + |
| 13 | +``` |
| 14 | +services/frontend/src/components/ui/button/ |
| 15 | +├── Button.vue # Enhanced button component with loading states |
| 16 | +└── index.ts # Button variants and exports |
| 17 | +``` |
| 18 | + |
| 19 | +## Features |
| 20 | + |
| 21 | +- **Automatic spinner** with `Loader2` icon from lucide-vue-next |
| 22 | +- **Auto-disable** during loading to prevent double submissions |
| 23 | +- **Optional loading text** to display custom messages |
| 24 | +- **Size-aware spinner** that scales with button size |
| 25 | +- **Works with all variants** (default, destructive, outline, etc.) |
| 26 | + |
| 27 | +## Props |
| 28 | + |
| 29 | +| Prop | Type | Default | Description | |
| 30 | +|------|------|---------|-------------| |
| 31 | +| `loading` | `boolean` | `false` | Shows spinner and disables button | |
| 32 | +| `loadingText` | `string` | `undefined` | Optional text during loading | |
| 33 | +| `disabled` | `boolean` | `false` | Disable independent of loading | |
| 34 | +| `variant` | `string` | `'default'` | Button style variant | |
| 35 | +| `size` | `string` | `'default'` | Button size (sm, default, lg, icon) | |
| 36 | + |
| 37 | +## Usage Example |
| 38 | + |
| 39 | +```vue |
| 40 | +<script setup lang="ts"> |
| 41 | +import { ref } from 'vue' |
| 42 | +import { Button } from '@/components/ui/button' |
| 43 | +import { toast } from 'vue-sonner' |
| 44 | +
|
| 45 | +const isSubmitting = ref(false) |
| 46 | +
|
| 47 | +const handleSubmit = async () => { |
| 48 | + isSubmitting.value = true |
| 49 | + try { |
| 50 | + await saveData() |
| 51 | + toast.success('Saved successfully') |
| 52 | + } catch (error) { |
| 53 | + toast.error('Save failed', { description: error.message }) |
| 54 | + } finally { |
| 55 | + isSubmitting.value = false |
| 56 | + } |
| 57 | +} |
| 58 | +</script> |
| 59 | +
|
| 60 | +<template> |
| 61 | + <Button |
| 62 | + :loading="isSubmitting" |
| 63 | + loading-text="Saving..." |
| 64 | + @click="handleSubmit" |
| 65 | + > |
| 66 | + Save Changes |
| 67 | + </Button> |
| 68 | +</template> |
| 69 | +``` |
| 70 | + |
| 71 | +## Implementation Details |
| 72 | + |
| 73 | +The component automatically: |
| 74 | +- Displays a spinning `Loader2` icon when `loading` is true |
| 75 | +- Hides the original slot content during loading |
| 76 | +- Shows `loadingText` alongside the spinner (if provided) |
| 77 | +- Disables the button to prevent multiple clicks |
| 78 | +- Adjusts spinner size based on button size prop |
| 79 | + |
| 80 | +For implementation details, see the source code at `services/frontend/src/components/ui/button/Button.vue`. |
| 81 | + |
| 82 | +## Related Documentation |
| 83 | + |
| 84 | +- [UI Design System](/development/frontend/ui-design-system) - Overall design patterns |
| 85 | +- [Global Sonner Toast System](/development/frontend/ui-design-global-sonner) - Toast notifications |
0 commit comments