Skip to content

Commit 361ea9b

Browse files
author
Lasim
committed
feat(frontend): add loading state and spinner to button component
1 parent 4cd25c4 commit 361ea9b

File tree

1 file changed

+31
-1
lines changed
  • services/frontend/src/components/ui/button

1 file changed

+31
-1
lines changed

services/frontend/src/components/ui/button/Button.vue

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
11
<script setup lang="ts">
22
import type { HTMLAttributes } from 'vue'
3+
import { computed } from 'vue'
34
import { Primitive, type PrimitiveProps } from 'reka-ui'
5+
import { Loader2 } from 'lucide-vue-next'
46
import { cn } from '@/lib/utils'
57
import { type ButtonVariants, buttonVariants } from '.'
68
79
interface Props extends PrimitiveProps {
810
variant?: ButtonVariants['variant']
911
size?: ButtonVariants['size']
1012
class?: HTMLAttributes['class']
13+
loading?: boolean
14+
loadingText?: string
15+
disabled?: boolean
1116
}
1217
1318
const props = withDefaults(defineProps<Props>(), {
1419
as: 'button',
20+
loading: false,
21+
disabled: false,
22+
})
23+
24+
// Compute the actual disabled state (disabled when loading or explicitly disabled)
25+
const isDisabled = computed(() => props.loading || props.disabled)
26+
27+
// Compute icon size based on button size
28+
const spinnerSize = computed(() => {
29+
switch (props.size) {
30+
case 'sm':
31+
return 'h-3 w-3'
32+
case 'lg':
33+
return 'h-5 w-5'
34+
default:
35+
return 'h-4 w-4'
36+
}
1537
})
1638
</script>
1739

@@ -21,7 +43,15 @@ const props = withDefaults(defineProps<Props>(), {
2143
:as="as"
2244
:as-child="asChild"
2345
:class="cn(buttonVariants({ variant, size }), props.class)"
46+
:disabled="isDisabled"
2447
>
25-
<slot />
48+
<Loader2
49+
v-if="loading"
50+
:class="cn(spinnerSize, 'animate-spin')"
51+
/>
52+
<template v-if="loading && loadingText">
53+
{{ loadingText }}
54+
</template>
55+
<slot v-else-if="!loading" />
2656
</Primitive>
2757
</template>

0 commit comments

Comments
 (0)