Files
RenewCMS/web/src/components/UpdateStatusBlock.vue
T

47 lines
1.4 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue'
export type UpdateTone = 'neutral' | 'success' | 'info' | 'warning' | 'error'
const TONE_CLASSES: Record<UpdateTone, { block: string; icon: string }> = {
neutral: { block: 'bg-muted', icon: 'text-toned' },
success: { block: 'bg-(--rc-success-soft)', icon: 'text-success' },
info: { block: 'bg-(--rc-info-soft)', icon: 'text-info' },
warning: { block: 'bg-(--rc-warning-soft)', icon: 'text-warning' },
error: { block: 'bg-(--rc-error-soft)', icon: 'text-error' },
}
const props = defineProps<{
tone: UpdateTone
icon: string
title: string
text: string
meta?: string
live?: 'polite' | 'off'
}>()
const toneClasses = computed(() => TONE_CLASSES[props.tone])
const spinning = computed(() => props.icon === 'i-lucide-loader-circle')
</script>
<template>
<div :aria-live="live ?? 'polite'" class="flex gap-3 p-3.5" :class="toneClasses.block">
<span class="flex pt-0.5">
<UIcon
:name="icon"
class="size-4.5 shrink-0"
:class="[
toneClasses.icon,
spinning ? 'animate-spin motion-reduce:animate-none' : '',
]"
/>
</span>
<div class="flex min-w-0 flex-1 flex-col gap-1">
<span class="text-base font-semibold text-highlighted">{{ title }}</span>
<span class="text-sm text-pretty text-toned">{{ text }}</span>
<slot />
<span v-if="meta" class="text-xs/5 text-muted">{{ meta }}</span>
</div>
</div>
</template>