feat(stage-layouts): align account dropdown with onboarding (#2439)
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { signOut } from '@proj-airi/stage-ui/libs/auth'
|
||||
import { useAuthStore } from '@proj-airi/stage-ui/stores/auth'
|
||||
import { Avatar } from '@proj-airi/ui'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { AnimatedContent, Avatar } from '@proj-airi/ui'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, ref } from 'vue'
|
||||
import {
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRoot,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from 'reka-ui'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
@@ -14,14 +21,8 @@ const { t } = useI18n()
|
||||
|
||||
const userName = computed(() => user.value?.name)
|
||||
const userAvatar = computed(() => user.value?.image)
|
||||
const showDropdown = ref(false)
|
||||
const dropdownRef = ref(null)
|
||||
|
||||
const formattedCredits = computed(() => credits.value.toLocaleString())
|
||||
|
||||
onClickOutside(dropdownRef, () => {
|
||||
showDropdown.value = false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -52,98 +53,139 @@ onClickOutside(dropdownRef, () => {
|
||||
</template>
|
||||
|
||||
<!-- Authenticated: Avatar Dropdown -->
|
||||
<div v-else ref="dropdownRef" class="relative">
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-2 border-2 border-neutral-100/60 rounded-full bg-neutral-50/70 p-1 pl-1 pr-3 backdrop-blur-md transition dark:border-neutral-800/30 dark:bg-neutral-800/70 hover:bg-neutral-100 dark:hover:bg-neutral-800"
|
||||
:class="{ 'ring-2 ring-primary-500/20': showDropdown }"
|
||||
aria-haspopup="true"
|
||||
:aria-label="userName || t('settings.pages.account.title')"
|
||||
:aria-expanded="showDropdown ? 'true' : 'false'"
|
||||
@click="showDropdown = !showDropdown"
|
||||
>
|
||||
<Avatar
|
||||
:src="userAvatar"
|
||||
<DropdownMenuRoot v-else>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<button
|
||||
type="button"
|
||||
:aria-label="userName || t('settings.pages.account.title')"
|
||||
:class="[
|
||||
'h-7 w-7 rounded-full',
|
||||
'bg-neutral-200 text-neutral-500 dark:bg-neutral-700 dark:text-neutral-400',
|
||||
'group flex items-center gap-2 rounded-full border-2 p-1 pl-1 pr-3 outline-none backdrop-blur-md',
|
||||
'border-neutral-100/60 bg-neutral-50/70 dark:border-neutral-800/30 dark:bg-neutral-800/70',
|
||||
'hover:bg-neutral-100 data-[state=open]:bg-neutral-100',
|
||||
'dark:hover:bg-neutral-800 dark:data-[state=open]:bg-neutral-800',
|
||||
'data-[state=open]:ring-2 data-[state=open]:ring-primary-500/20',
|
||||
'transition-colors duration-200 ease-in-out',
|
||||
]"
|
||||
/>
|
||||
|
||||
<span v-if="userName" class="max-w-[100px] truncate text-sm text-neutral-700 font-medium hidden sm:block dark:text-neutral-200">
|
||||
{{ userName }}
|
||||
</span>
|
||||
<div
|
||||
class="i-solar:alt-arrow-down-linear text-neutral-400 transition-transform duration-200"
|
||||
:class="{ 'rotate-180': showDropdown }"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<Transition
|
||||
enter-active-class="transition duration-200 ease-out"
|
||||
enter-from-class="translate-y-1 opacity-0"
|
||||
enter-to-class="translate-y-0 opacity-100"
|
||||
leave-active-class="transition duration-150 ease-in"
|
||||
leave-from-class="translate-y-0 opacity-100"
|
||||
leave-to-class="translate-y-1 opacity-0"
|
||||
>
|
||||
<div
|
||||
v-if="showDropdown"
|
||||
class="absolute right-0 top-full z-50 mt-2 w-60 origin-top-right border border-neutral-200/60 rounded-xl bg-white/90 p-1 shadow-xl backdrop-blur-xl divide-y divide-neutral-100 dark:border-neutral-800/60 dark:bg-neutral-900/90 dark:divide-neutral-800"
|
||||
>
|
||||
<div class="px-3 py-2">
|
||||
<p class="text-xs text-neutral-500 dark:text-neutral-400">
|
||||
Signed in as
|
||||
</p>
|
||||
<p class="truncate text-sm text-neutral-900 font-medium dark:text-white">
|
||||
{{ userName }}
|
||||
</p>
|
||||
<div class="mt-1 flex items-center gap-1.5 text-xs text-primary-600 font-medium dark:text-primary-400">
|
||||
<div class="i-solar:battery-charge-bold-duotone text-sm" />
|
||||
<span>{{ formattedCredits }} Flux</span>
|
||||
<Avatar
|
||||
:src="userAvatar"
|
||||
:class="[
|
||||
'h-7 w-7 rounded-full',
|
||||
'bg-neutral-200 text-neutral-500 dark:bg-neutral-700 dark:text-neutral-400',
|
||||
]"
|
||||
/>
|
||||
|
||||
<span
|
||||
v-if="userName"
|
||||
:class="[
|
||||
'max-w-[100px] hidden truncate text-sm font-medium sm:block',
|
||||
'text-neutral-700 dark:text-neutral-200',
|
||||
]"
|
||||
>
|
||||
{{ userName }}
|
||||
</span>
|
||||
<div
|
||||
:class="[
|
||||
'i-solar:alt-arrow-down-linear text-neutral-400',
|
||||
'transition-transform duration-200',
|
||||
'group-data-[state=open]:rotate-180',
|
||||
]"
|
||||
/>
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuContent
|
||||
as-child
|
||||
align="end"
|
||||
side="bottom"
|
||||
:side-offset="6"
|
||||
:class="[
|
||||
'z-10000 w-60 rounded-xl border p-1 shadow-lg outline-none backdrop-blur-md',
|
||||
'border-neutral-100/80 bg-neutral-100/80 text-neutral-700',
|
||||
'dark:border-neutral-800/60 dark:bg-neutral-800/80 dark:text-neutral-100',
|
||||
]"
|
||||
>
|
||||
<AnimatedContent>
|
||||
<div class="px-3 py-2">
|
||||
<p class="text-xs text-neutral-500 dark:text-neutral-400">
|
||||
Signed in as
|
||||
</p>
|
||||
<p class="truncate text-sm text-neutral-900 font-medium dark:text-white">
|
||||
{{ userName }}
|
||||
</p>
|
||||
<div class="mt-1 flex items-center gap-1.5 text-xs text-primary-600 font-medium dark:text-primary-400">
|
||||
<div class="i-solar:battery-charge-bold-duotone text-sm" />
|
||||
<span>{{ formattedCredits }} Flux</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="py-1">
|
||||
<RouterLink
|
||||
to="/settings/account"
|
||||
class="group w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm text-neutral-700 transition hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
@click="showDropdown = false"
|
||||
>
|
||||
<div class="i-solar:user-id-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Profile
|
||||
</RouterLink>
|
||||
<DropdownMenuSeparator :class="['mx-2 my-1 h-px bg-neutral-200/80 dark:bg-neutral-700/80']" />
|
||||
|
||||
<RouterLink
|
||||
to="/settings/flux"
|
||||
class="group w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm text-neutral-700 transition hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
@click="showDropdown = false"
|
||||
>
|
||||
<div class="i-solar:battery-charge-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Flux
|
||||
</RouterLink>
|
||||
<DropdownMenuItem as-child>
|
||||
<RouterLink
|
||||
to="/settings/account"
|
||||
:class="[
|
||||
'group w-full flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2',
|
||||
'text-sm leading-none outline-none text-neutral-700 dark:text-neutral-200',
|
||||
'data-[highlighted]:bg-primary-100/80 dark:data-[highlighted]:bg-primary-900/40',
|
||||
'transition-colors duration-150 ease-in-out',
|
||||
]"
|
||||
>
|
||||
<div class="i-solar:user-id-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Profile
|
||||
</RouterLink>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<RouterLink
|
||||
to="/settings"
|
||||
class="group w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm text-neutral-700 transition hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
@click="showDropdown = false"
|
||||
>
|
||||
<div class="i-solar:settings-minimalistic-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Settings
|
||||
</RouterLink>
|
||||
</div>
|
||||
<DropdownMenuItem as-child>
|
||||
<RouterLink
|
||||
to="/settings/flux"
|
||||
:class="[
|
||||
'group w-full flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2',
|
||||
'text-sm leading-none outline-none text-neutral-700 dark:text-neutral-200',
|
||||
'data-[highlighted]:bg-primary-100/80 dark:data-[highlighted]:bg-primary-900/40',
|
||||
'transition-colors duration-150 ease-in-out',
|
||||
]"
|
||||
>
|
||||
<div class="i-solar:battery-charge-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Flux
|
||||
</RouterLink>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<div class="py-1">
|
||||
<button
|
||||
class="group w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm text-red-600 transition hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
|
||||
@click="signOut"
|
||||
>
|
||||
<div class="i-solar:logout-3-bold-duotone text-lg transition group-hover:text-red-600 dark:group-hover:text-red-400" />
|
||||
Sign out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
<DropdownMenuItem as-child>
|
||||
<RouterLink
|
||||
to="/settings"
|
||||
:class="[
|
||||
'group w-full flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2',
|
||||
'text-sm leading-none outline-none text-neutral-700 dark:text-neutral-200',
|
||||
'data-[highlighted]:bg-primary-100/80 dark:data-[highlighted]:bg-primary-900/40',
|
||||
'transition-colors duration-150 ease-in-out',
|
||||
]"
|
||||
>
|
||||
<div class="i-solar:settings-minimalistic-bold-duotone text-lg text-neutral-400 transition group-hover:text-primary-500" />
|
||||
Settings
|
||||
</RouterLink>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator :class="['mx-2 my-1 h-px bg-neutral-200/80 dark:bg-neutral-700/80']" />
|
||||
|
||||
<DropdownMenuItem as-child>
|
||||
<button
|
||||
:class="[
|
||||
'group w-full flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2',
|
||||
'text-sm leading-none outline-none text-red-600 dark:text-red-400',
|
||||
'data-[highlighted]:bg-red-50 dark:data-[highlighted]:bg-red-900/20',
|
||||
'transition-colors duration-150 ease-in-out',
|
||||
]"
|
||||
@click="signOut"
|
||||
>
|
||||
<div class="i-solar:logout-3-bold-duotone text-lg transition group-hover:text-red-600 dark:group-hover:text-red-400" />
|
||||
Sign out
|
||||
</button>
|
||||
</DropdownMenuItem>
|
||||
</AnimatedContent>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuRoot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user