feat(ui): responsive sidebar (breakoff: 1024px)

environments/review-docs-feat-z0hkbz/deployments/19889
upsiflu 2024-12-18 13:14:59 +01:00
rodzic 7aad9b6729
commit 1909a484c3
2 zmienionych plików z 66 dodań i 9 usunięć

Wyświetl plik

@ -28,7 +28,13 @@ onKeyboardShortcut('h', () => isShortcutsModalOpen.value = !isShortcutsModalOpen
<style scoped lang="scss">
.grid {
display: grid !important;
grid-template-columns: 300px 5fr;
grid-template-columns: 100%;
grid-template-rows: min-content;
min-height: 100vh;
@media screen and (min-width: 1024px) {
grid-template-columns: 300px 5fr;
grid-template-rows: 100%;
}
}
</style>

Wyświetl plik

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, watch } from 'vue'
import { useUploadsStore } from '../stores/upload'
import { useI18n } from 'vue-i18n'
import { useStore } from '~/store'
@ -12,6 +12,22 @@ import UserMenu from './UserMenu.vue'
import Button from '~/components/ui/Button.vue'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/layout/Spacer.vue'
import { useRoute, useRouter } from 'vue-router'
/*
Sidebar on slim screen
- While screen is slim, sidebar is drawn on top of screen
- While screen is slim, When new route is loaded, top-sidebar is auto-collapsed: `watch(() => route.path, () => (isCollapsed.value = true))`
- While screen is slim, top-sidebar can be expanded and collapsed with additional hamburger button on top-right
*/
const isCollapsed = ref(false)
const route = useRoute()
watch(() => route.path, () => ( isCollapsed.value = true ))
const { openShortcutsModal } = defineProps<{ openShortcutsModal: ()=> void }>()
@ -29,7 +45,7 @@ const uploads = useUploadsStore()
</script>
<template>
<aside :class="[$style.sidebar, $style['sticky-content']]" v-bind="color('default solid raised')">
<Layout aside :class="[$style.sidebar, $style['sticky-content']]" v-bind="color('default solid raised')">
<Layout flex no-gap header style="justify-content:space-between; padding-right:8px;">
<Link to="/"
:class="$style['logo']"
@ -70,9 +86,11 @@ const uploads = useUploadsStore()
</Link>
<UserMenu :showShortcutsModal="openShortcutsModal"/>
<Button round ghost icon="bi-list large" class="hide-on-desktop" @click="isCollapsed=!isCollapsed"/>
</Layout>
</Layout>
<Layout no-gap stack :class="$style['button-list']">
<Layout no-gap stack :class="$style['menu-links']" v-if="!isCollapsed">
<div :class="$style.search">
<Input
v-model="searchQuery"
@ -81,6 +99,28 @@ const uploads = useUploadsStore()
:placeholder="t('components.audio.SearchBar.placeholder.search')"
/>
</div>
<!-- Sign up, Log in -->
<div style="display:contents;" class="hide-on-desktop" v-if="!store.state.auth.authenticated">
<Layout flex no-gap>
<Link :to="{ name: 'login' }"
primary solid ful
icon="bi-box-arrow-in-right"
style="flex-grow:1"
>
{{ t('components.common.UserMenu.link.login') }}
</Link>
<Link :to="{ name: 'signup' }"
secondary solid
icon="bi-person-square"
style="flex-grow:1"
>
{{ t('components.common.UserMenu.link.signup') }}
</Link>
</Layout>
<Spacer :size="32" />
</div>
<nav style="display:contents;">
<Link to="/library"
ghost
@ -143,19 +183,16 @@ const uploads = useUploadsStore()
</Link>
</nav>
</Layout>
</aside>
</Layout>
</template>
<style module lang="scss">
.sidebar {
height: 100%;
display:flex;
flex-direction:column;
&.sticky-content {
position: sticky;
height: 100%;
max-height: 100vh;
overflow: auto;
top: 0;
@ -239,8 +276,22 @@ const uploads = useUploadsStore()
font-size: 14px;
line-height: 1.2;
}
.button-list {
.menu-links {
padding: 0 16px 32px;
flex-grow: 1
}
}
@media screen and (min-width: 1024px) {
height: 100%;
:global(.hide-on-desktop){
display: none !important;
}
&.sticky-content {
position: sticky;
height: 100%;
}
}
}