fix(front): consistent user avatars

This commit is contained in:
ArneBo 2025-01-24 02:52:44 +01:00
parent 6f62b92218
commit ef8d2f7ac2
7 changed files with 105 additions and 59 deletions

View File

@ -19,16 +19,18 @@ const defaultAvatarStyle = computed(() => ({ backgroundColor: `#${actorColor.val
v-if="actor.icon && actor.icon.urls.original" v-if="actor.icon && actor.icon.urls.original"
alt="" alt=""
:src="actor.icon.urls.medium_square_crop" :src="actor.icon.urls.medium_square_crop"
class="ui avatar circular image" class="ui tiny avatar circular image"
> >
<i <span
v-else v-else
:style="defaultAvatarStyle" :style="defaultAvatarStyle"
class="ui avatar circular label" class="ui tiny avatar circular label"
>{{ actor.preferred_username?.[0] || "" }}</i> >
{{ actor.preferred_username?.[0] || "" }}
</span>
</template> </template>
<style lang="scss"> <style lang="scss" scoped>
.ui.circular.avatar { .ui.circular.avatar {
float: left; float: left;
text-align: center; text-align: center;
@ -36,6 +38,8 @@ const defaultAvatarStyle = computed(() => ({ backgroundColor: `#${actorColor.val
&.label { &.label {
align-content: center; align-content: center;
padding: 4px 8px;
margin-right: 8px;
} }
} }

View File

@ -78,9 +78,5 @@ a.username {
display: flex; display: flex;
align-items: center; align-items: center;
} }
i.label {
padding: 4px 8px;
margin-right: 8px;
}
} }
</style> </style>

View File

@ -6,16 +6,20 @@ import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useStore } from '~/store' import { useStore } from '~/store'
import Link from '~/components/ui/Link.vue'
interface Props { interface Props {
user: User user: User
avatar?: boolean avatar?: boolean
discrete?: boolean
} }
const store = useStore() const store = useStore()
const { t } = useI18n() const { t } = useI18n()
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
avatar: true avatar: true,
discrete: false
}) })
const userColor = computed(() => intToRGB(hashCode(props.user.username + props.user.id))) const userColor = computed(() => intToRGB(hashCode(props.user.username + props.user.id)))
@ -23,21 +27,40 @@ const defaultAvatarStyle = computed(() => ({ backgroundColor: `#${userColor.valu
</script> </script>
<template> <template>
<span class="component-user-link"> <Link
:to="user"
:title="user.full_username"
class="username"
:solid="!discrete"
:round="!discrete"
>
<span class="center">
<template v-if="avatar"> <template v-if="avatar">
<img <img
v-if="user.avatar && user.avatar.urls.medium_square_crop" v-if="user.avatar && user.avatar.urls.medium_square_crop"
v-lazy="store.getters['instance/absoluteUrl'](user.avatar.urls.medium_square_crop)" v-lazy="store.getters['instance/absoluteUrl'](user.avatar.urls.medium_square_crop)"
class="ui tiny circular avatar" class="ui avatar tiny circular image"
alt="" alt=""
> >
<span <span
v-else v-else
:style="defaultAvatarStyle" :style="defaultAvatarStyle"
class="ui circular label" class="ui tiny avatar circular label"
>{{ user.username[0] }}</span> >
{{ user.username[0] }}
</span>
&nbsp; &nbsp;
</template> </template>
{{ t('components.common.UserLink.link.username', {username: user.username}) }} {{ t('components.common.UserLink.link.username', {username: user.username}) }}
</span> </span>
</Link>
</template> </template>
<style lang="scss" scoped>
a.username {
span.center {
display: flex;
align-items: center;
}
}
</style>

View File

@ -1,12 +1,15 @@
.ui.tiny.avatar.image {
position: relative;
top: -0.5em;
width: 3em;
}
.ui.tiny.avatar { .ui.tiny.avatar {
width: 28px; width: 28px;
height: 28px; height: 28px;
display: block;
float: left;
text-align: center;
font-size: 1em !important; font-size: 1em !important;
border-radius: 50%;
&.label {
align-content: center;
padding: 4px 8px;
}
} }

View File

@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n'
import { computed, ref} from 'vue' import { computed, ref} from 'vue'
import { useStore } from '~/store' import { useStore } from '~/store'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { hashCode, intToRGB } from '~/utils/color'
import useThemeList from '~/composables/useThemeList' import useThemeList from '~/composables/useThemeList'
import useTheme from '~/composables/useTheme' import useTheme from '~/composables/useTheme'
@ -24,9 +23,6 @@ const { theme } = useTheme()
const isOpen = ref(false) const isOpen = ref(false)
const actorColor = computed(() => intToRGB(hashCode(store.state.auth.profile.full_username)))
const defaultAvatarStyle = computed(() => ({ backgroundColor: `#${actorColor.value}` }))
const labels = computed(() => ({ const labels = computed(() => ({
profile: t('components.common.UserMenu.link.profile'), profile: t('components.common.UserMenu.link.profile'),
settings: t('components.common.UserMenu.link.settings'), settings: t('components.common.UserMenu.link.settings'),
@ -53,6 +49,7 @@ const labels = computed(() => ({
round round
square-small square-small
ghost ghost
class="user-menu"
:ariaPressed="isOpen ? true : undefined" :ariaPressed="isOpen ? true : undefined"
> >
<img <img
@ -63,8 +60,7 @@ const labels = computed(() => ({
> >
<span <span
v-else-if="store.state.auth.authenticated" v-else-if="store.state.auth.authenticated"
:style="defaultAvatarStyle" class="ui tiny avatar circular label"
class="ui avatar circular label"
> >
{{ store.state.auth.profile?.full_username?.[0] || "" }} {{ store.state.auth.profile?.full_username?.[0] || "" }}
</span> </span>
@ -163,25 +159,48 @@ const labels = computed(() => ({
</Popover> </Popover>
</template> </template>
<style scoped lang="scss"> <style lang="scss" scoped>
header > nav button.button { header > nav button.button {
padding: 10px; padding: 10px;
&:has(img) { &.user-menu {
padding: 4px; padding: 0px !important;
.avatar {
width: 40px;
height: 40px; height: 40px;
border-radius: 50%;
@include light-theme {
&.label {
background-color: var(--fw-gray-900);
color: var(--fw-beige-300);
&:hover {
color: var(--fw-color);
background-color: var(--hover-background-color);
} }
} }
nav.button-list { }
@include dark-theme {
&.label {
background-color: var(--fw-beige-400);
color: var(--fw-gray-900);
&:hover {
color: var(--fw-color);
background-color: var(--hover-background-color);
}
}
}
}
}
}
nav.button-list {
width: 100%; width: 100%;
a:hover { a:hover {
background-color: transparent; background-color: transparent;
border: none; border: none;
} }
} }
.avatar {
width: 30px;
height: 30px;
border-radius: 50%;
}
</style> </style>

View File

@ -216,6 +216,8 @@ const recentActivity = ref(0)
font-size: 100px; font-size: 100px;
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
text-align: center;
align-content: center;
background-color: var(--fw-gray-500); background-color: var(--fw-gray-500);
border-radius: 50%; border-radius: 50%;
width: 176px; width: 176px;

View File

@ -256,7 +256,6 @@ const isOpen = ref(false)
<Spacer :size="8" /> <Spacer :size="8" />
<div class="extra content"> <div class="extra content">
<actor-link <actor-link
style="color: var(--link-color)"
:actor="library.actor" :actor="library.actor"
/> />
</div> </div>