funkwhale/front/src/components/ui/Button.vue

80 lines
1.7 KiB
Vue

<script setup lang="ts">
import { ref, computed, useSlots, onMounted } from 'vue'
import { type ColorProps, useColor } from '~/composables/colors'
import Loader from '~/components/ui/Loader.vue'
interface Props {
variant?: 'solid' | 'outline' | 'ghost'
width?: 'standard' | 'auto' | 'full'
alignText?: 'left' | 'center' | 'right'
isActive?: boolean
isLoading?: boolean
shadow?: boolean
round?: boolean
icon?: string
onClick?: (...args: any[]) => void | Promise<void>
autofocus? : boolean
}
const props = defineProps<Props & ColorProps>()
const color = useColor(() => props.color)
const slots = useSlots()
const iconOnly = computed(() => !!props.icon && !slots.default)
const internalLoader = ref(false)
const isLoading = computed(() => props.isLoading || internalLoader.value)
const button = ref()
console.log("props.autofocus", props.autofocus)
const click = async (...args: any[]) => {
internalLoader.value = true
try {
await props.onClick?.(...args)
} finally {
internalLoader.value = false
}
}
onMounted(() => {
if (props.autofocus) button.value.focus();
})
</script>
<template>
<button ref="button" class="funkwhale is-colored button" :class="[
color,
'is-' + (variant ?? 'solid'),
'is-' + (width ?? 'standard'),
'is-aligned-' + (alignText ?? 'center'),
{
'is-active': isActive,
'is-loading': isLoading,
'icon-only': iconOnly,
'has-icon': !!icon,
'is-round': round,
'is-shadow': shadow
}
]" @click="click">
<i v-if="icon" :class="['bi', icon]" />
<span>
<slot />
</span>
<Loader v-if="isLoading" :container="false" />
</button>
</template>
<style lang="scss">
@import './button.scss'
</style>