289 lines
8.6 KiB
Vue
289 lines
8.6 KiB
Vue
<template>
|
|
<button
|
|
class="sidebar__menu-icon text-white"
|
|
:aria-expanded="isOpen.toString()"
|
|
aria-controls="sidebar"
|
|
:aria-label="t('Toggle Sidebar')"
|
|
@click.stop="toggleSidebar"
|
|
>
|
|
<span v-if="!isOpen"><svg width="28" height="18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 18c-.425 0-.781-.144-1.068-.432A1.459 1.459 0 0 1 .5 16.5c-.001-.424.143-.78.432-1.068A1.454 1.454 0 0 1 2 15h24c.425 0 .782.144 1.07.432.288.288.431.644.43 1.068-.001.424-.145.78-.432 1.07A1.435 1.435 0 0 1 26 18H2Zm0-7.5c-.425 0-.781-.144-1.068-.432A1.459 1.459 0 0 1 .5 9c-.001-.424.143-.78.432-1.068A1.454 1.454 0 0 1 2 7.5h24c.425 0 .782.144 1.07.432.288.288.431.644.43 1.068-.001.424-.145.78-.432 1.07A1.435 1.435 0 0 1 26 10.5H2ZM2 3c-.425 0-.781-.144-1.068-.432A1.459 1.459 0 0 1 .5 1.5C.499 1.076.643.72.932.432A1.454 1.454 0 0 1 2 0h24c.425 0 .782.144 1.07.432.288.288.431.644.43 1.068-.001.424-.145.78-.432 1.07A1.435 1.435 0 0 1 26 3H2Z" fill="currentColor" /></svg></span>
|
|
<span v-else><svg width="36" height="36" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m18 20.1-7.35 7.35c-.275.275-.625.413-1.05.413-.425 0-.775-.138-1.05-.413-.275-.275-.412-.625-.412-1.05 0-.425.137-.775.412-1.05L15.9 18l-7.35-7.35c-.275-.275-.412-.625-.412-1.05 0-.425.137-.775.412-1.05.275-.275.625-.413 1.05-.413.425 0 .775.138 1.05.413L18 15.9l7.35-7.35c.275-.275.625-.413 1.05-.413.425 0 .775.138 1.05.413.275.275.413.625.413 1.05 0 .425-.138.775-.413 1.05L20.1 18l7.35 7.35c.275.275.413.625.413 1.05 0 .425-.138.775-.413 1.05-.275.275-.625.413-1.05.413-.425 0-.775-.138-1.05-.413L18 20.1Z" fill="#585C5E" /></svg></span>
|
|
</button>
|
|
<div
|
|
ref="sidebarContainer"
|
|
:class="['sidebar', { 'sidebar--open': isOpen }]
|
|
"
|
|
role="navigation"
|
|
aria-label="Hauptnavigation"
|
|
:aria-hidden="(!isOpen).toString()"
|
|
>
|
|
<ul class="sidebar__main-menu">
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/account')"
|
|
class="sidebar__link"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-user sidebar__icon" /><span class="sidebar__text">{{ t('Account') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
<li v-if="dataStore.user.team_subscription_plan == '0' && dataStore.user.enterprise_subscription_plan == '0' && (dataStore.user.basic_subscription_plan == '1')" class="sidebar__item">
|
|
<nuxt-link :to="localePath('/settings/subscription')" class="sidebar__link" :tabindex="isOpen ? 0 : -1">
|
|
<i class="fa-solid fa-credit-card sidebar__icon" /><span class="sidebar__text">{{ t('Subscription') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/soundscape')"
|
|
class="sidebar__link"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-volume-high sidebar__icon" /><span class="sidebar__text">{{ t('Settings') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/about')"
|
|
class="sidebar__link"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-circle-info sidebar__icon" /><span class="sidebar__text"> {{ t('About Mindboost') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/faq')"
|
|
class="sidebar__link"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-circle-question sidebar__icon" /><span class="sidebar__text">{{ t('FAQ') }} </span>
|
|
</nuxt-link>
|
|
</li>
|
|
</ul>
|
|
<ul class="sidebar__secondary-menu">
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/imprint')"
|
|
class="sidebar__link sidebar__link--secondary"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-stamp sidebar__icon" /><span class="sidebar__text">{{ t('Imprint') }} </span>
|
|
</nuxt-link>
|
|
</li>
|
|
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/dataprotection')"
|
|
class="sidebar__link sidebar__link--secondary"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
>
|
|
<i class="fa-solid fa-shield sidebar__icon" /><span class="sidebar__text">{{ t('Data Protection') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
|
|
<li class="sidebar__item">
|
|
<nuxt-link
|
|
:to="localePath('/settings/termsandcondition')"
|
|
class="sidebar__link sidebar__link--secondary"
|
|
:tabindex="isOpen ? 0 : -1"
|
|
:aria-hidden="!isOpen"
|
|
@blur="handleBlur"
|
|
>
|
|
<i class="fa-solid fa-scale-balanced sidebar__icon" /><span class="sidebar__text">{{ t('Terms & Conditions') }}</span>
|
|
</nuxt-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { onMounted, onBeforeUnmount, ref } from 'vue'
|
|
import { useUserStore } from '~/stores/user'
|
|
|
|
export default {
|
|
setup () {
|
|
const isOpen = ref(false)
|
|
const sidebarContainer = ref(null)
|
|
const dataStore = useUserStore()
|
|
const { t } = useI18n()
|
|
const localePath = useLocalePath()
|
|
|
|
const toggleSidebar = () => {
|
|
isOpen.value = !isOpen.value
|
|
}
|
|
|
|
const handleClickOutside = (event) => {
|
|
if (sidebarContainer.value && !sidebarContainer.value.contains(event.target)) {
|
|
isOpen.value = false
|
|
}
|
|
}
|
|
|
|
const handleBlur = () => {
|
|
// Timeout nötig, um neuen Fokus zu berücksichtigen
|
|
setTimeout(() => {
|
|
const active = document.activeElement
|
|
if (
|
|
isOpen.value &&
|
|
sidebarContainer.value &&
|
|
!sidebarContainer.value.contains(active)
|
|
) {
|
|
isOpen.value = false
|
|
}
|
|
}, 10)
|
|
}
|
|
|
|
const handleEscape = (e) => {
|
|
if (e.key === 'Escape' && isOpen.value) {
|
|
isOpen.value = false
|
|
document.querySelector('.sidebar__menu-icon')?.focus()
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', handleClickOutside)
|
|
document.addEventListener('keydown', handleEscape)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener('click', handleClickOutside)
|
|
document.removeEventListener('keydown', handleEscape)
|
|
})
|
|
|
|
return { t, localePath, dataStore, isOpen, toggleSidebar, sidebarContainer, handleBlur }
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.sidebar {
|
|
position: fixed;
|
|
top: 0;
|
|
right: -350px;
|
|
width: 350px;
|
|
height: 100%;
|
|
background-color: #fff;
|
|
transition: right 0.3s ease;
|
|
z-index: 1000;
|
|
padding: 6em 0em 2em;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
|
|
&--open {
|
|
box-shadow: -2px 0 10px rgba(0, 0, 0, 0.2);
|
|
right: 0;
|
|
}
|
|
|
|
&.sidebar--settings {
|
|
background-color: rgb(244, 245, 247);
|
|
position: unset;
|
|
width: 100%;
|
|
height: 100%;
|
|
padding-top: 0;
|
|
|
|
.sidebar__item {
|
|
&::after {
|
|
content: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__menu-icon {
|
|
background: none;
|
|
border: none;
|
|
cursor: pointer;
|
|
z-index: 1001;
|
|
}
|
|
|
|
&__main-menu,
|
|
&__secondary-menu {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
&__item {
|
|
position: relative;
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: 1em;
|
|
right: 1em;
|
|
bottom: 0;
|
|
height: 2px;
|
|
background-color: #f3f3f3;
|
|
transition: 250ms ease-in-out;
|
|
}
|
|
|
|
&:hover {
|
|
&::after {
|
|
background-color: #e9c046;
|
|
}
|
|
}
|
|
|
|
&:last-child {
|
|
&::after {
|
|
content: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
.sidebar__link {
|
|
text-decoration: none;
|
|
color: #585C5E;
|
|
font-size: 1.2em;
|
|
display: block;
|
|
width: 100%;
|
|
padding: 0.75em 1em;
|
|
font-weight: 700;
|
|
transition: 250ms ease-in-out;
|
|
|
|
&:hover {
|
|
background-color: #e9c046;
|
|
color: white;
|
|
}
|
|
|
|
&--secondary {
|
|
font-size: 0.9em;
|
|
color: #85878C;
|
|
|
|
&:hover {
|
|
background-color: transparent;
|
|
color: #85878C;
|
|
text-decoration: underline;
|
|
}
|
|
}
|
|
|
|
}
|
|
.sidebar__icon {
|
|
display: none;
|
|
}
|
|
|
|
&__secondary-menu {
|
|
.sidebar__item {
|
|
&::after{
|
|
content: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
&.sidebar--settings {
|
|
|
|
.sidebar__icon {
|
|
|
|
@media only screen and (max-width: 576px) {
|
|
display: block;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|