Files
social-media/frontend/src/components/AppAvatar.vue
Jonathan Bourdon 1ca6ab7117
All checks were successful
deploy-socialize / image (push) Successful in 50s
deploy-socialize / deploy (push) Successful in 19s
feat: centralize frontend Vuetify styling
2026-05-08 13:45:42 -04:00

81 lines
1.8 KiB
Vue

<script setup>
import { computed } from 'vue';
const props = defineProps({
name: {
type: String,
default: '',
},
email: {
type: String,
default: '',
},
src: {
type: String,
default: null,
},
size: {
type: String,
default: 'md',
},
});
const initials = computed(() => {
const basis = props.name?.trim() || props.email?.trim() || '?';
const parts = basis.split(/[\s@._-]+/).filter(Boolean);
if (!parts.length) {
return '?';
}
if (parts.length === 1) {
return parts[0].slice(0, 2).toUpperCase();
}
return `${parts[0][0] ?? ''}${parts[1][0] ?? ''}`.toUpperCase();
});
const classes = computed(() => ({
avatar: true,
'avatar-sm': props.size === 'sm',
'avatar-md': props.size === 'md',
'avatar-lg': props.size === 'lg',
}));
</script>
<template>
<div :class="classes">
<img
v-if="src"
:src="src"
:alt="name || email || 'Avatar'"
/>
<span v-else>{{ initials }}</span>
</div>
</template>
<style scoped>
@reference "@/assets/main.css";
.avatar {
@apply inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full font-black uppercase;
background: linear-gradient(135deg, rgba(15, 118, 110, 0.16) 0%, rgba(255, 138, 61, 0.18) 100%);
color: var(--app-color-on-surface);
}
.avatar img {
@apply h-full w-full object-cover;
}
.avatar-sm {
@apply h-9 w-9 text-xs;
}
.avatar-md {
@apply h-11 w-11 text-sm;
}
.avatar-lg {
@apply h-14 w-14 text-base;
}
</style>