56 lines
1.3 KiB
Vue
56 lines
1.3 KiB
Vue
<template>
|
|
<span
|
|
class="inline-flex shrink-0 items-center justify-center rounded-full"
|
|
:class="sizeClasses"
|
|
:title="user.username"
|
|
>
|
|
<img
|
|
v-if="user.avatarUrl && !imgError"
|
|
:src="user.avatarUrl"
|
|
:alt="user.username"
|
|
class="h-full w-full rounded-full object-cover"
|
|
@error="imgError = true"
|
|
/>
|
|
<span
|
|
v-else
|
|
class="flex h-full w-full items-center justify-center rounded-full bg-primary-500 font-bold text-white"
|
|
:class="textSizeClass"
|
|
>
|
|
{{ user.username.substring(0, 2).toUpperCase() }}
|
|
</span>
|
|
</span>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const props = defineProps<{
|
|
user: { id?: number; username: string; avatarUrl?: string | null }
|
|
size?: 'xs' | 'sm' | 'md' | 'lg'
|
|
}>()
|
|
|
|
const imgError = ref(false)
|
|
|
|
watch(() => props.user.avatarUrl, () => {
|
|
imgError.value = false
|
|
})
|
|
|
|
const sizeClasses = computed(() => {
|
|
const map = {
|
|
xs: 'h-5 w-5',
|
|
sm: 'h-6 w-6',
|
|
md: 'h-8 w-8',
|
|
lg: 'h-12 w-12',
|
|
}
|
|
return map[props.size ?? 'sm']
|
|
})
|
|
|
|
const textSizeClass = computed(() => {
|
|
const map = {
|
|
xs: 'text-[10px]',
|
|
sm: 'text-xs',
|
|
md: 'text-sm',
|
|
lg: 'text-base',
|
|
}
|
|
return map[props.size ?? 'sm']
|
|
})
|
|
</script>
|