feat(ui): [WIP] use new Ui components for user menu in sidebar
This commit is contained in:
parent
adec453e83
commit
32cf6c2e3d
|
@ -5,7 +5,7 @@ import { hashCode, intToRGB } from '~/utils/color'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
actor: Actor
|
actor: { full_username : string; preferred_username?:string; icon?:Actor["icon"] }
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
|
@ -36,6 +36,12 @@ const { width: popoverWidth, height: popoverHeight } = useElementBounding(popove
|
||||||
whenever(open, update, { immediate: true })
|
whenever(open, update, { immediate: true })
|
||||||
|
|
||||||
const { width: screenWidth, height: screenHeight } = useScreenSize()
|
const { width: screenWidth, height: screenHeight } = useScreenSize()
|
||||||
|
|
||||||
|
// TODO (basic functionality):
|
||||||
|
// - I can't operate the popup with a keyboard. Remove barrier for people not using a mouse (A11y)
|
||||||
|
// - Switching to submenus is error-prone. When moving cursor into freshly opened submenu, it should not close if the cursor crosses another menu item
|
||||||
|
// - Large menus disappear. When menus get big, they need to scroll.
|
||||||
|
|
||||||
const position = computed(() => {
|
const position = computed(() => {
|
||||||
if (positioning === 'vertical' || isMobile.value) {
|
if (positioning === 'vertical' || isMobile.value) {
|
||||||
let offsetTop = top.value + height.value
|
let offsetTop = top.value + height.value
|
||||||
|
|
|
@ -25,3 +25,7 @@ emit('internal:id', id)
|
||||||
<slot name="after" />
|
<slot name="after" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
div { color:var(--fw-text-color); }
|
||||||
|
</style>
|
||||||
|
|
|
@ -7,6 +7,8 @@ import { useStore } from '~/store'
|
||||||
import Input from '~/components/ui/Input.vue'
|
import Input from '~/components/ui/Input.vue'
|
||||||
import Pill from '~/components/ui/Pill.vue'
|
import Pill from '~/components/ui/Pill.vue'
|
||||||
import Link from '~/components/ui/Link.vue'
|
import Link from '~/components/ui/Link.vue'
|
||||||
|
import ActorAvatar from '~/components/common/ActorAvatar.vue'
|
||||||
|
import UserMenu from './UserMenu.vue'
|
||||||
|
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
|
|
||||||
|
@ -57,25 +59,8 @@ const uploads = useUploadsStore()
|
||||||
</Transition>
|
</Transition>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link to="/settings"
|
<UserMenu />
|
||||||
icon="bi-person-fill"
|
|
||||||
color="secondary"
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-if="store.state.auth.authenticated && store.state.auth.profile?.avatar?.urls.medium_square_crop"
|
|
||||||
alt=""
|
|
||||||
:src="store.getters['instance/absoluteUrl'](store.state.auth.profile?.avatar.urls.medium_square_crop)"
|
|
||||||
>
|
|
||||||
<actor-avatar
|
|
||||||
v-else-if="store.state.auth.authenticated"
|
|
||||||
:actor="{preferred_username: store.state.auth.username, full_username: store.state.auth.username,}"
|
|
||||||
/>
|
|
||||||
<i
|
|
||||||
v-else
|
|
||||||
class="cog icon"
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="search">
|
<div class="search">
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { SUPPORTED_LOCALES, setI18nLanguage } from '~/init/locale'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useStore } from '~/store'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
import useThemeList from '~/composables/useThemeList'
|
||||||
|
import useTheme from '~/composables/useTheme'
|
||||||
|
|
||||||
|
import OptionsButton from '~/components/ui/button/Options.vue'
|
||||||
|
import Popover from '~/components/ui/Popover.vue'
|
||||||
|
import PopoverCheckbox from '~/components/ui/popover/PopoverCheckbox.vue'
|
||||||
|
import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
|
||||||
|
import PopoverRadio from '~/components/ui/popover/PopoverRadio.vue'
|
||||||
|
import PopoverRadioItem from '~/components/ui/popover/PopoverRadioItem.vue'
|
||||||
|
import PopoverSubmenu from '~/components/ui/popover/PopoverSubmenu.vue'
|
||||||
|
|
||||||
|
interface Events {
|
||||||
|
(e: 'show:shortcuts-modal'): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const store = useStore()
|
||||||
|
|
||||||
|
const emit = defineEmits<Events>()
|
||||||
|
|
||||||
|
const { t, locale } = useI18n()
|
||||||
|
|
||||||
|
const themes = useThemeList()
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
|
const labels = computed(() => ({
|
||||||
|
profile: t('components.common.UserMenu.link.profile'),
|
||||||
|
settings: t('components.common.UserMenu.link.settings'),
|
||||||
|
logout: t('components.common.UserMenu.link.logout'),
|
||||||
|
about: t('components.common.UserMenu.link.about'),
|
||||||
|
shortcuts: t('components.common.UserMenu.label.shortcuts'),
|
||||||
|
support: t('components.common.UserMenu.link.support'),
|
||||||
|
forum: t('components.common.UserMenu.link.forum'),
|
||||||
|
docs: t('components.common.UserMenu.link.docs'),
|
||||||
|
language: t('components.common.UserMenu.label.language'),
|
||||||
|
theme: t('components.common.UserMenu.label.theme'),
|
||||||
|
chat: t('components.common.UserMenu.link.chat'),
|
||||||
|
git: t('components.common.UserMenu.link.git'),
|
||||||
|
login: t('components.common.UserMenu.link.login'),
|
||||||
|
signup: t('components.common.UserMenu.link.signup'),
|
||||||
|
notifications: t('components.common.UserMenu.link.notifications')
|
||||||
|
}))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Popover>
|
||||||
|
<template #default="{ toggleOpen }">
|
||||||
|
<OptionsButton @click="toggleOpen">
|
||||||
|
<img
|
||||||
|
v-if="store.state.auth.authenticated && store.state.auth.profile?.avatar?.urls.medium_square_crop"
|
||||||
|
alt=""
|
||||||
|
:src="store.getters['instance/absoluteUrl'](store.state.auth.profile?.avatar.urls.medium_square_crop)"
|
||||||
|
>
|
||||||
|
<ActorAvatar
|
||||||
|
v-else-if="store.state.auth.authenticated"
|
||||||
|
:actor="{preferred_username: store.state.auth.username, full_username: store.state.auth.username,}"
|
||||||
|
/>
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="cog icon"
|
||||||
|
/>
|
||||||
|
</OptionsButton>
|
||||||
|
</template>
|
||||||
|
<template #items>
|
||||||
|
<PopoverSubmenu>
|
||||||
|
<i class="bi bi-music-note-list" />
|
||||||
|
Change language
|
||||||
|
<template #items>
|
||||||
|
<PopoverItem v-for="(language, key) in SUPPORTED_LOCALES"
|
||||||
|
:key="key"
|
||||||
|
@click="setI18nLanguage(key)" >
|
||||||
|
{{ language }}
|
||||||
|
</PopoverItem>
|
||||||
|
</template>
|
||||||
|
</PopoverSubmenu>
|
||||||
|
<hr />
|
||||||
|
<PopoverItem>
|
||||||
|
<i class="bi bi-heart" />
|
||||||
|
Add to favorites
|
||||||
|
</PopoverItem>
|
||||||
|
<PopoverSubmenu>
|
||||||
|
<i class="bi bi-collection" />
|
||||||
|
Organize and share
|
||||||
|
<template #items>
|
||||||
|
<PopoverCheckbox v-model="bc">
|
||||||
|
Bandcamp
|
||||||
|
<template #after>
|
||||||
|
<Popover>
|
||||||
|
<template #default="{ toggleOpen }">
|
||||||
|
<Pill
|
||||||
|
@click.stop="toggleOpen"
|
||||||
|
:blue="bcPrivacy === 'pod'"
|
||||||
|
:red="bcPrivacy === 'public'"
|
||||||
|
>
|
||||||
|
{{ bcPrivacy }}
|
||||||
|
</Pill>
|
||||||
|
</template>
|
||||||
|
<template #items>
|
||||||
|
<PopoverRadio v-model="bcPrivacy" :choices="privacyChoices" />
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
</PopoverCheckbox>
|
||||||
|
<PopoverCheckbox v-model="cc">
|
||||||
|
Creative Commons
|
||||||
|
<template #after>
|
||||||
|
<Popover v-model:open="isOpen">
|
||||||
|
<template #default="{ toggleOpen }">
|
||||||
|
<Pill
|
||||||
|
@click="toggleOpen"
|
||||||
|
:blue="ccPrivacy === 'pod'"
|
||||||
|
:red="ccPrivacy === 'public'"
|
||||||
|
>
|
||||||
|
{{ ccPrivacy }}
|
||||||
|
</Pill>
|
||||||
|
</template>
|
||||||
|
<template #items>
|
||||||
|
<PopoverRadio v-model="ccPrivacy" :choices="privacyChoices" />
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
</PopoverCheckbox>
|
||||||
|
<hr />
|
||||||
|
<PopoverItem>
|
||||||
|
<i class="bi bi-plus-lg" />
|
||||||
|
New library
|
||||||
|
</PopoverItem>
|
||||||
|
<hr />
|
||||||
|
<PopoverCheckbox v-model="share">
|
||||||
|
Share by link
|
||||||
|
<template #after>
|
||||||
|
<Button @click.stop color="secondary" round icon="bi-link" />
|
||||||
|
<Button @click.stop color="secondary" round icon="bi-code" />
|
||||||
|
</template>
|
||||||
|
</PopoverCheckbox>
|
||||||
|
</template>
|
||||||
|
</PopoverSubmenu>
|
||||||
|
<PopoverItem>
|
||||||
|
<i class="bi bi-cloud-download" />
|
||||||
|
Download
|
||||||
|
</PopoverItem>
|
||||||
|
<hr />
|
||||||
|
<PopoverItem>
|
||||||
|
<i class="bi bi-exclamation" />
|
||||||
|
Report
|
||||||
|
</PopoverItem>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
Loading…
Reference in New Issue