Files
speckle-server/packages/frontend-2/components/user/Avatar.vue
T
Kristaps Fabians Geikins b02a07e2b6 feat: Frontend 2.0 MVP
2023-05-08 10:47:01 +03:00

107 lines
2.2 KiB
Vue

<template>
<div
:class="[
'text-foreground-on-primary flex shrink-0 items-center justify-center overflow-hidden rounded-full font-semibold uppercase transition',
sizeClasses,
bgClasses,
borderClasses,
hoverClasses,
activeClasses
]"
>
<slot>
<div
v-if="user?.avatar"
class="h-full w-full bg-cover bg-center bg-no-repeat"
:style="{ backgroundImage: `url('${user.avatar}')` }"
/>
<div
v-else-if="initials"
class="flex h-full w-full select-none items-center justify-center"
>
{{ initials }}
</div>
<div v-else><UserCircleIcon :class="iconClasses" /></div>
</slot>
</div>
</template>
<script setup lang="ts">
import { UserCircleIcon } from '@heroicons/vue/24/solid'
import { graphql } from '~~/lib/common/generated/gql'
import {
AvatarUserType,
UserAvatarSize,
useAvatarSizeClasses
} from '~~/lib/user/composables/avatar'
graphql(`
fragment AppAuthorAvatar on AppAuthor {
id
name
avatar
}
`)
graphql(`
fragment LimitedUserAvatar on LimitedUser {
id
name
avatar
}
`)
graphql(`
fragment ActiveUserAvatar on User {
id
name
avatar
}
`)
const props = withDefaults(
defineProps<{
user?: AvatarUserType | null
size?: UserAvatarSize
hoverEffect?: boolean
active?: boolean
noBorder?: boolean
noBg?: boolean
}>(),
{
size: 'base',
hoverEffect: false,
user: undefined
}
)
const { sizeClasses, iconClasses } = useAvatarSizeClasses({ props: toRefs(props) })
const initials = computed(() => {
if (!props.user?.name?.length) return
const parts = props.user.name.split(' ')
if (props.size === 'sm' || props.size === 'xs') return parts[0][0]
return parts[0][0] + (parts[1]?.[0] || '')
})
const borderClasses = computed(() => {
if (props.noBorder) return ''
return 'border-2 border-foundation'
})
const bgClasses = computed(() => {
if (props.noBg) return ''
return 'bg-primary'
})
const hoverClasses = computed(() => {
if (props.hoverEffect)
return 'hover:border-primary focus:border-primary active:scale-95'
return ''
})
const activeClasses = computed(() => {
if (props.active) return 'border-primary'
return ''
})
</script>