First commit
This commit is contained in:
65
frontend/src/components/common/LoadingSpinner.vue
Normal file
65
frontend/src/components/common/LoadingSpinner.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div
|
||||
:class="['spinner', sizeClasses, colorClass]"
|
||||
role="status"
|
||||
:aria-label="t('common.loading')"
|
||||
>
|
||||
<span class="sr-only">{{ t('common.loading') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
type SpinnerSize = 'sm' | 'md' | 'lg' | 'xl'
|
||||
type SpinnerColor = 'primary' | 'secondary' | 'white' | 'gray'
|
||||
|
||||
interface Props {
|
||||
size?: SpinnerSize
|
||||
color?: SpinnerColor
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
size: 'md',
|
||||
color: 'primary'
|
||||
})
|
||||
|
||||
const sizeClasses = computed(() => {
|
||||
const sizes: Record<SpinnerSize, string> = {
|
||||
sm: 'w-4 h-4 border-2',
|
||||
md: 'w-8 h-8 border-2',
|
||||
lg: 'w-12 h-12 border-[3px]',
|
||||
xl: 'w-16 h-16 border-4'
|
||||
}
|
||||
return sizes[props.size]
|
||||
})
|
||||
|
||||
const colorClass = computed(() => {
|
||||
const colors: Record<SpinnerColor, string> = {
|
||||
primary: 'text-primary-500',
|
||||
secondary: 'text-gray-500 dark:text-dark-400',
|
||||
white: 'text-white',
|
||||
gray: 'text-gray-400 dark:text-dark-500'
|
||||
}
|
||||
return colors[props.color]
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.spinner {
|
||||
@apply inline-block rounded-full border-solid border-current border-r-transparent;
|
||||
animation: spin 0.75s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user