feat(layout): show avatar/login state in the top-right menu trigger
Replace the hamburger icon on the fixed top-right menu button with a context-aware affordance: the user's avatar when logged in (first initial when they have no picture), or a login icon when logged out. Opens the same profile/menu sheet either way; aria-label reflects the state. overflow-hidden + the avatar filling the round button keeps it clipped to the chip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1c004df99c
commit
8a0f40910a
1 changed files with 16 additions and 4 deletions
|
|
@ -2,13 +2,16 @@
|
||||||
import { ref, type Component } from 'vue'
|
import { ref, type Component } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Menu } from 'lucide-vue-next'
|
import { LogIn } from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
Sheet,
|
Sheet,
|
||||||
SheetContent,
|
SheetContent,
|
||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from '@/components/ui/sheet'
|
} from '@/components/ui/sheet'
|
||||||
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||||
import { Separator } from '@/components/ui/separator'
|
import { Separator } from '@/components/ui/separator'
|
||||||
|
import { useAuth } from '@/composables/useAuthService'
|
||||||
|
import { useCurrentUserAvatar } from '@/composables/useCurrentUserAvatar'
|
||||||
import ProfileSheetContent from './ProfileSheetContent.vue'
|
import ProfileSheetContent from './ProfileSheetContent.vue'
|
||||||
|
|
||||||
export interface SidebarNavItem {
|
export interface SidebarNavItem {
|
||||||
|
|
@ -35,6 +38,9 @@ const { t } = useI18n()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
|
|
||||||
|
const { isAuthenticated } = useAuth()
|
||||||
|
const { pictureUrl, displayName, fallbackInitial } = useCurrentUserAvatar()
|
||||||
|
|
||||||
function handleClick(item: SidebarNavItem) {
|
function handleClick(item: SidebarNavItem) {
|
||||||
if (item.path) router.push(item.path)
|
if (item.path) router.push(item.path)
|
||||||
item.onClick?.()
|
item.onClick?.()
|
||||||
|
|
@ -46,11 +52,17 @@ function handleClick(item: SidebarNavItem) {
|
||||||
<Sheet v-model:open="open">
|
<Sheet v-model:open="open">
|
||||||
<SheetTrigger as-child>
|
<SheetTrigger as-child>
|
||||||
<button
|
<button
|
||||||
class="fixed top-0 right-0 z-40 m-3 inline-flex items-center justify-center rounded-full border bg-background/90 backdrop-blur supports-[backdrop-filter]:bg-background/60 h-9 w-9 text-muted-foreground hover:text-foreground hover:bg-accent transition-colors shadow-sm"
|
class="fixed top-0 right-0 z-40 m-3 inline-flex items-center justify-center overflow-hidden rounded-full border bg-background/90 backdrop-blur supports-[backdrop-filter]:bg-background/60 h-9 w-9 text-muted-foreground hover:text-foreground hover:bg-accent transition-colors shadow-sm"
|
||||||
style="margin-top: calc(env(safe-area-inset-top) + 0.75rem); margin-right: calc(env(safe-area-inset-right) + 0.75rem)"
|
style="margin-top: calc(env(safe-area-inset-top) + 0.75rem); margin-right: calc(env(safe-area-inset-right) + 0.75rem)"
|
||||||
:aria-label="t('common.nav.menu')"
|
:aria-label="isAuthenticated ? t('common.nav.profile') : t('common.nav.login')"
|
||||||
>
|
>
|
||||||
<Menu class="w-5 h-5" />
|
<!-- Logged in: avatar (image, or first initial). Logged out: a
|
||||||
|
login icon. Opens the same profile/menu sheet either way. -->
|
||||||
|
<Avatar v-if="isAuthenticated" class="h-full w-full">
|
||||||
|
<AvatarImage v-if="pictureUrl" :src="pictureUrl" :alt="displayName ?? ''" />
|
||||||
|
<AvatarFallback>{{ fallbackInitial || '?' }}</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
<LogIn v-else class="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent side="right" class="w-80 sm:w-96 max-w-full overflow-y-auto overflow-x-hidden">
|
<SheetContent side="right" class="w-80 sm:w-96 max-w-full overflow-y-auto overflow-x-hidden">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue