Feature/avatar updates (#258)

* avatar status indicator fixed

* fix for missing placeholder
This commit is contained in:
Sqrcz
2023-12-15 11:43:59 +01:00
committed by GitHub
parent fa3fb58bda
commit cfdf6bf676
3 changed files with 43 additions and 42 deletions

View File

@@ -1,18 +1,23 @@
<template> <template>
<div class="relative"> <div class="relative">
<img
v-if="img && !imageError"
:alt="alt"
:class="avatarClasses"
:src="img"
@error="setImageError"
>
<div <div
v-else
:class="avatarPlaceholderWrapperClasses" :class="avatarPlaceholderWrapperClasses"
> >
<img
v-if="img && !imageError"
:alt="alt"
:class="avatarClasses"
:src="img"
@error="setImageError"
>
<div
v-else-if="!initials && hasPlaceholder"
:class="avatarPlaceholderClasses"
>
<slot name="placeholder" />
</div>
<svg <svg
v-if="!initials && !hasPlaceholder" v-else-if="!img && !initials"
:class="avatarPlaceholderClasses" :class="avatarPlaceholderClasses"
fill="currentColor" fill="currentColor"
viewBox="0 0 20 20" viewBox="0 0 20 20"
@@ -24,24 +29,18 @@
fill-rule="evenodd" fill-rule="evenodd"
/> />
</svg> </svg>
<div
v-if="!initials && hasPlaceholder"
:class="avatarPlaceholderClasses"
>
<slot name="placeholder" />
</div>
<div <div
v-else v-else
:class="avatarPlaceholderInitialsClasses" :class="avatarPlaceholderInitialsClasses"
> >
{{ initials }} {{ initials }}
</div> </div>
<span
v-if="status"
:class="avatarDotClasses"
:data-pos="statusPosition"
/>
</div> </div>
<span
v-if="status"
:class="avatarDotClasses"
:data-pos="statusPosition"
/>
</div> </div>
</template> </template>

View File

@@ -6,7 +6,7 @@ import type {
AvatarStatusPosition, AvatarStatusPosition,
AvatarType, AvatarType,
} from '@/components/FwbAvatar/types' } from '@/components/FwbAvatar/types'
import classNames from 'classnames' import { useMergeClasses } from '@/composables/useMergeClasses'
const avatarSizeClasses: Record<AvatarSize, string> = { const avatarSizeClasses: Record<AvatarSize, string> = {
xs: 'w-6 h-6', xs: 'w-6 h-6',
@@ -39,7 +39,8 @@ const avatarStatusDotPositionClasses: Record<avatarDotIndicatorPositionClasses,
} }
const avatarPlaceholderDefaultClasses = 'absolute w-auto h-auto text-gray-400' const avatarPlaceholderDefaultClasses = 'absolute w-auto h-auto text-gray-400'
const avatarPlaceholderWrapperDefaultClasses = 'inline-flex overflow-hidden relative justify-center items-center bg-gray-100 dark:bg-gray-600' const avatarPlaceholderWrapperDefaultClasses = 'flex overflow-hidden relative justify-center items-center'
const avatarPlaceholderWrapperBackgroundClasses = 'bg-gray-100 dark:bg-gray-600'
const avatarPlaceholderInitialsDefaultClasses = 'font-medium text-gray-600 dark:text-gray-300' const avatarPlaceholderInitialsDefaultClasses = 'font-medium text-gray-600 dark:text-gray-300'
const avatarPlaceholderSizes = { const avatarPlaceholderSizes = {
xs: 'bottom-0', xs: 'bottom-0',
@@ -67,41 +68,42 @@ export function useAvatarClasses (props: UseAvatarClassesProps): {
avatarPlaceholderWrapperClasses: Ref<string> avatarPlaceholderWrapperClasses: Ref<string>
avatarPlaceholderInitialsClasses: Ref<string> avatarPlaceholderInitialsClasses: Ref<string>
} { } {
const avatarClasses = computed<string>(() => { const avatarClasses = computed<string>(() =>
return classNames( useMergeClasses([
avatarSizeClasses[props.size.value], avatarSizeClasses[props.size.value],
avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'], avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'],
props.bordered.value ? avatarBorderedClasses : '', props.bordered.value ? avatarBorderedClasses : '',
props.stacked.value ? 'border-2 border-white dark:border-gray-800' : '', props.stacked.value ? 'border-2 border-white dark:border-gray-800' : '',
) ]),
}) )
const avatarDotClasses = computed<string>(() => { const avatarDotClasses = computed<string>(() => {
const avatarType = `${props.statusPosition.value}-${props.rounded.value ? 'rounded' : 'default'}` const avatarType = `${props.statusPosition.value}-${props.rounded.value ? 'rounded' : 'default'}`
return classNames( return useMergeClasses([
avatarStatusDotDefaultClasses, avatarStatusDotDefaultClasses,
avatarStatusDotClasses[props.status.value], avatarStatusDotClasses[props.status.value],
avatarStatusDotPositionClasses[avatarType as avatarDotIndicatorPositionClasses], avatarStatusDotPositionClasses[avatarType as avatarDotIndicatorPositionClasses],
) ])
}) })
const avatarPlaceholderClasses = computed<string>(() => { const avatarPlaceholderClasses = computed<string>(() =>
return classNames( useMergeClasses([
avatarPlaceholderDefaultClasses, avatarPlaceholderDefaultClasses,
avatarPlaceholderSizes[props.size.value], avatarPlaceholderSizes[props.size.value],
) ]),
}) )
const avatarPlaceholderWrapperClasses = computed<string>(() => { const avatarPlaceholderWrapperClasses = computed<string>(() =>
return classNames( useMergeClasses([
avatarPlaceholderWrapperDefaultClasses, avatarPlaceholderWrapperDefaultClasses,
avatarSizeClasses[props.size.value], avatarSizeClasses[props.size.value],
avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'], avatarTypeClasses[props.rounded.value ? 'rounded' : 'default'],
) (props.img.value && props.bordered.value) ? '' : avatarPlaceholderWrapperBackgroundClasses,
}) props.bordered.value ? ' overflow-visible' : '',
const avatarPlaceholderInitialsClasses = computed<string>(() => { ]),
return classNames( )
const avatarPlaceholderInitialsClasses = computed<string>(() =>
useMergeClasses([
avatarPlaceholderInitialsDefaultClasses, avatarPlaceholderInitialsDefaultClasses,
) ]),
}) )
// TODO: Avatar Initials
return { return {
avatarClasses, avatarClasses,

View File

@@ -1,4 +1,4 @@
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
export const useMergeClasses = (componentClasses: string): string => export const useMergeClasses = (componentClasses: string | string[]): string =>
twMerge(componentClasses) twMerge(componentClasses)