web/satellite/vuetify-poc: improve navigation drawer on small screens
This change improves the behaviour of the navigation drawer. It is now able to automatically close on resize to smaller screen sizes and vice versa, and also by close by clicking outside the drawer. Issue: https://github.com/storj/storj/issues/6266 Change-Id: I1aee465a546abbf1369c48f6827b058523c5da21
This commit is contained in:
parent
e4d6829971
commit
1a8913e7a0
@ -5,7 +5,7 @@
|
||||
<v-app>
|
||||
<session-wrapper>
|
||||
<default-bar show-nav-drawer-button />
|
||||
<account-nav v-if="appStore.state.isNavigationDrawerShown" />
|
||||
<account-nav />
|
||||
<default-view />
|
||||
</session-wrapper>
|
||||
</v-app>
|
||||
|
@ -2,11 +2,11 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer class="py-1">
|
||||
<v-navigation-drawer v-model="model" class="py-1">
|
||||
<v-sheet>
|
||||
<v-list class="px-2" color="default" variant="flat">
|
||||
<template v-if="pathBeforeAccountPage">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link :to="pathBeforeAccountPage" @click="() => trackPageVisitEvent(pathBeforeAccountPage)">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link :to="pathBeforeAccountPage" @click="() => registerLinkClick(pathBeforeAccountPage)">
|
||||
<template #prepend>
|
||||
<img src="@poc/assets/icon-back-tonal.svg" alt="Project">
|
||||
<!-- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -22,7 +22,7 @@
|
||||
</template>
|
||||
|
||||
<!-- All Projects -->
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<v-list-item class="pa-4 rounded-lg" link router-link to="/projects" @click="() => registerLinkClick('/projects')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-prosject.svg" alt="Project" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -40,7 +40,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="settings" class="my-1 py-3" rounded="lg" @click="() => trackPageVisitEvent('/settings')">
|
||||
<v-list-item link router-link to="settings" class="my-1 py-3" rounded="lg" @click="() => registerLinkClick('/settings')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-settings.svg" alt="Account Settings" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -52,7 +52,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link to="billing" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/billing')">
|
||||
<v-list-item link router-link to="billing" class="my-1" rounded="lg" @click="() => registerLinkClick('/billing')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-card.svg" alt="Billing" class="mr-3"> -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -71,7 +71,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { computed, onBeforeMount } from 'vue';
|
||||
import {
|
||||
VNavigationDrawer,
|
||||
VSheet,
|
||||
@ -80,6 +80,7 @@ import {
|
||||
VListItemTitle,
|
||||
VDivider,
|
||||
} from 'vuetify/components';
|
||||
import { useDisplay } from 'vuetify';
|
||||
|
||||
import { useAppStore } from '@poc/store/appStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
@ -87,6 +88,13 @@ import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const { mdAndDown } = useDisplay();
|
||||
|
||||
const model = computed<boolean>({
|
||||
get: () => appStore.state.isNavigationDrawerShown,
|
||||
set: value => appStore.toggleNavigationDrawer(value),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the path to the most recent non-account-related page.
|
||||
*/
|
||||
@ -96,10 +104,26 @@ const pathBeforeAccountPage = computed((): string | null => {
|
||||
return path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Conditionally closes the navigation drawer and tracks page visit.
|
||||
*/
|
||||
function registerLinkClick(page: string | null): void {
|
||||
if (mdAndDown.value) {
|
||||
model.value = false;
|
||||
}
|
||||
trackPageVisitEvent(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends "Page Visit" event to segment and opens link.
|
||||
*/
|
||||
function trackPageVisitEvent(page: string | null): void {
|
||||
if (page) analyticsStore.pageVisit(page);
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (mdAndDown.value) {
|
||||
model.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -97,7 +97,7 @@
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item link class="my-1 rounded-lg">
|
||||
<v-list-item link class="my-1 rounded-lg" @click="closeSideNav">
|
||||
<template #prepend>
|
||||
<img src="@poc/assets/icon-upgrade.svg" alt="Upgrade">
|
||||
</template>
|
||||
@ -106,7 +106,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link class="my-1 rounded-lg" router-link to="/account/billing">
|
||||
<v-list-item link class="my-1 rounded-lg" router-link to="/account/billing" @click="closeSideNav">
|
||||
<template #prepend>
|
||||
<img src="@poc/assets/icon-card.svg" alt="Billing">
|
||||
</template>
|
||||
@ -115,7 +115,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link class="my-1 rounded-lg" router-link to="/account/settings">
|
||||
<v-list-item link class="my-1 rounded-lg" router-link to="/account/settings" @click="closeSideNav">
|
||||
<template #prepend>
|
||||
<img src="@poc/assets/icon-settings.svg" alt="Account Settings">
|
||||
</template>
|
||||
@ -222,6 +222,10 @@ watch(() => theme.global.current.value.dark, (newVal: boolean) => {
|
||||
toggleTheme(localStorage.getItem('theme') || 'light');
|
||||
activeTheme.value = theme.global.current.value.dark ? 1 : 0;
|
||||
|
||||
function closeSideNav(): void {
|
||||
appStore.toggleNavigationDrawer(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out user and navigates to login page.
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<session-wrapper v-else>
|
||||
<default-bar show-nav-drawer-button />
|
||||
<ProjectNav v-if="appStore.state.isNavigationDrawerShown" />
|
||||
<ProjectNav />
|
||||
<default-view />
|
||||
</session-wrapper>
|
||||
</v-app>
|
||||
@ -86,10 +86,6 @@ watch(() => route.params.projectId, async newId => {
|
||||
* Pre-fetches user`s and project information.
|
||||
*/
|
||||
onBeforeMount(async () => {
|
||||
if (document.body.clientWidth < 1280) {
|
||||
appStore.toggleNavigationDrawer(false);
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// See LICENSE for copying information.
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer class="py-1">
|
||||
<v-navigation-drawer v-model="model" class="py-1">
|
||||
<v-sheet>
|
||||
<v-list class="px-2" color="default" variant="flat">
|
||||
<!-- Project -->
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Project Menu -->
|
||||
<v-list class="pa-2">
|
||||
<!-- My Projects -->
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => registerLinkClick('/projects')">
|
||||
<template #prepend>
|
||||
<!-- <img src="@poc/assets/icon-project.svg" alt="Projects"> -->
|
||||
<IconProject />
|
||||
@ -36,7 +36,7 @@
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<!-- Shared With Me -->
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<v-list-item rounded="lg" link router-link to="/projects" @click="() => registerLinkClick('/projects')">
|
||||
<template #prepend>
|
||||
<IconProject />
|
||||
</template>
|
||||
@ -69,7 +69,7 @@
|
||||
<!-- <v-divider class="my-2"></v-divider> -->
|
||||
|
||||
<!-- View All Projects -->
|
||||
<v-list-item link rounded="lg" router-link to="/projects" @click="() => trackPageVisitEvent('/projects')">
|
||||
<v-list-item link rounded="lg" router-link to="/projects" @click="() => registerLinkClick('/projects')">
|
||||
<template #prepend>
|
||||
<IconAllProjects />
|
||||
</template>
|
||||
@ -117,7 +117,7 @@
|
||||
|
||||
<v-divider class="my-2" />
|
||||
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/dashboard`" class="my-1 py-3" rounded="lg" @click="() => trackPageVisitEvent('/dashboard')">
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/dashboard`" class="my-1 py-3" rounded="lg" @click="() => registerLinkClick('/dashboard')">
|
||||
<template #prepend>
|
||||
<IconDashboard />
|
||||
</template>
|
||||
@ -126,7 +126,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/buckets`" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/buckets')">
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/buckets`" class="my-1" rounded="lg" @click="() => registerLinkClick('/buckets')">
|
||||
<template #prepend>
|
||||
<IconBucket />
|
||||
</template>
|
||||
@ -135,7 +135,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/bucket`" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/bucket')">
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/bucket`" class="my-1" rounded="lg" @click="() => registerLinkClick('/bucket')">
|
||||
<template #prepend>
|
||||
<IconBrowse />
|
||||
</template>
|
||||
@ -144,7 +144,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/access`" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/access')">
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/access`" class="my-1" rounded="lg" @click="() => registerLinkClick('/access')">
|
||||
<template #prepend>
|
||||
<IconAccess />
|
||||
</template>
|
||||
@ -153,7 +153,7 @@
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/team`" class="my-1" rounded="lg" @click="() => trackPageVisitEvent('/team')">
|
||||
<v-list-item link router-link :to="`/projects/${selectedProject.id}/team`" class="my-1" rounded="lg" @click="() => registerLinkClick('/team')">
|
||||
<template #prepend>
|
||||
<IconTeam />
|
||||
</template>
|
||||
@ -236,7 +236,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, onBeforeMount, ref } from 'vue';
|
||||
import {
|
||||
VNavigationDrawer,
|
||||
VSheet,
|
||||
@ -248,10 +248,12 @@ import {
|
||||
VChip,
|
||||
VDivider,
|
||||
} from 'vuetify/components';
|
||||
import { useDisplay } from 'vuetify';
|
||||
|
||||
import { Project } from '@/types/projects';
|
||||
import { useProjectsStore } from '@/store/modules/projectsStore';
|
||||
import { useAnalyticsStore } from '@/store/modules/analyticsStore';
|
||||
import { useAppStore } from '@poc/store/appStore';
|
||||
|
||||
import IconProject from '@poc/components/icons/IconProject.vue';
|
||||
import IconSettings from '@poc/components/icons/IconSettings.vue';
|
||||
@ -271,6 +273,14 @@ import CreateProjectDialog from '@poc/components/dialogs/CreateProjectDialog.vue
|
||||
|
||||
const analyticsStore = useAnalyticsStore();
|
||||
const projectsStore = useProjectsStore();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const { mdAndDown } = useDisplay();
|
||||
|
||||
const model = computed<boolean>({
|
||||
get: () => appStore.state.isNavigationDrawerShown,
|
||||
set: value => appStore.toggleNavigationDrawer(value),
|
||||
});
|
||||
|
||||
const isCreateProjectDialogShown = ref<boolean>(false);
|
||||
|
||||
@ -281,10 +291,26 @@ const selectedProject = computed((): Project => {
|
||||
return projectsStore.state.selectedProject;
|
||||
});
|
||||
|
||||
/**
|
||||
* Conditionally closes the navigation drawer and tracks page visit.
|
||||
*/
|
||||
function registerLinkClick(page: string): void {
|
||||
if (mdAndDown.value) {
|
||||
model.value = false;
|
||||
}
|
||||
trackPageVisitEvent(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends "Page Visit" event to segment and opens link.
|
||||
*/
|
||||
function trackPageVisitEvent(page: string): void {
|
||||
analyticsStore.pageVisit(page);
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (mdAndDown.value) {
|
||||
model.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -20,10 +20,6 @@ html {
|
||||
--v-theme-overlay-multiplier: 0.75;
|
||||
}
|
||||
|
||||
.v-navigation-drawer {
|
||||
// box-shadow: 0 3px 4px rgba(var(--v-theme-on-surface), 0.05) !important;
|
||||
transform: translateX(0) !important;
|
||||
}
|
||||
.v-app-bar.v-toolbar {
|
||||
border-bottom: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
// box-shadow: 0 1px 3px rgba(var(--v-theme-on-surface), 0.05) !important;
|
||||
|
Loading…
Reference in New Issue
Block a user