All checks were successful
Setup EC2 Tools / setup-server (push) Successful in 1m46s
49 lines
1.4 KiB
Vue
49 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import type { HTMLAttributes } from "vue"
|
|
import { computed, ref, watch } from "vue"
|
|
import { AvatarRoot } from "reka-ui"
|
|
import { IconUser } from "@tabler/icons-vue"
|
|
import { cn } from "@/lib/utils"
|
|
import { getInitials } from "@/composables/useInitials"
|
|
|
|
const props = defineProps<{
|
|
class?: HTMLAttributes["class"]
|
|
src?: string | null
|
|
name?: string
|
|
fallbackClass?: HTMLAttributes["class"]
|
|
}>()
|
|
|
|
const hasError = ref(false)
|
|
|
|
watch(() => props.src, () => {
|
|
hasError.value = false
|
|
})
|
|
|
|
const hasProps = computed(() => props.src !== undefined || props.name !== undefined)
|
|
const initials = computed(() => (props.name ? getInitials(props.name) : ''))
|
|
</script>
|
|
|
|
<template>
|
|
<AvatarRoot
|
|
data-slot="avatar"
|
|
:class="cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', props.class)"
|
|
>
|
|
<template v-if="hasProps">
|
|
<img
|
|
v-if="src && !hasError"
|
|
:src="src"
|
|
:alt="name"
|
|
class="aspect-square size-full object-cover"
|
|
@error="hasError = true"
|
|
/>
|
|
<div
|
|
v-else
|
|
:class="cn('flex size-full items-center justify-center bg-muted text-xs font-bold text-foreground select-none', props.fallbackClass)"
|
|
>
|
|
<span v-if="initials">{{ initials }}</span>
|
|
<IconUser v-else class="size-1/2 opacity-70" />
|
|
</div>
|
|
</template>
|
|
<slot v-else />
|
|
</AvatarRoot>
|
|
</template>
|