aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-04-15 12:21:09 +0200
committerGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-04-15 12:21:09 +0200
commit1e67fa6e0bede8c055d9e4cb9bf7f97423bc9bdf (patch)
tree5b7874b3258b6872966b8453839cb72317c494e2
parentf872972e69aeb4fde4c17f0c122ca3fd4aa1c56c (diff)
downloadit-tools-1e67fa6e0bede8c055d9e4cb9bf7f97423bc9bdf.tar.gz
it-tools-1e67fa6e0bede8c055d9e4cb9bf7f97423bc9bdf.tar.zst
it-tools-1e67fa6e0bede8c055d9e4cb9bf7f97423bc9bdf.zip
feat: mobile friendly menu
-rw-r--r--src/components/MenuLayout.vue47
-rw-r--r--src/layouts/base.layout.vue97
-rw-r--r--src/layouts/tool.layout.vue6
-rw-r--r--src/stores/style.store.ts6
4 files changed, 121 insertions, 35 deletions
diff --git a/src/components/MenuLayout.vue b/src/components/MenuLayout.vue
new file mode 100644
index 0000000..48150c1
--- /dev/null
+++ b/src/components/MenuLayout.vue
@@ -0,0 +1,47 @@
+<template>
+ <n-layout has-sider>
+ <n-layout-sider bordered collapse-mode="width" :collapsed-width="0" :width="240" :collapsed="isMenuCollapsed"
+ @collapse="isMenuCollapsed = true" @expand="isMenuCollapsed = false" :show-trigger="false"
+ :native-scrollbar="false" :position="siderPosition">
+ <slot name="sider" />
+ </n-layout-sider>
+ <n-layout class="content">
+ <slot name="content" />
+ <div class="overlay" v-show="isSmallScreen && !isMenuCollapsed" @click="isMenuCollapsed = true" />
+ </n-layout>
+ </n-layout>
+</template>
+
+<script setup lang="ts">
+import { useStyleStore } from '@/stores/style.store';
+import { toRefs } from 'vue';
+import { computed } from 'vue';
+
+const styleStore = useStyleStore()
+const { isMenuCollapsed, isSmallScreen } = toRefs(styleStore)
+const siderPosition = computed(() => isSmallScreen.value ? 'absolute' : 'static')
+</script>
+
+<style lang="less" scoped>
+.overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #00000080;
+ cursor: pointer;
+}
+
+.content {
+
+ // background-color: #f1f5f9;
+ ::v-deep(.n-layout-scroll-container) {
+ padding: 26px;
+ }
+}
+
+.n-layout {
+ height: 100vh;
+}
+</style> \ No newline at end of file
diff --git a/src/layouts/base.layout.vue b/src/layouts/base.layout.vue
index 1d1480c..d20e4a0 100644
--- a/src/layouts/base.layout.vue
+++ b/src/layouts/base.layout.vue
@@ -2,15 +2,15 @@
import { NIcon } from 'naive-ui';
import { h, ref, type Component } from 'vue';
import { RouterLink, useRoute } from 'vue-router';
-import { Heart, BrandGithub, BrandTwitter, Moon, Sun } from '@vicons/tabler'
+import { Heart, BrandGithub, BrandTwitter, Moon, Sun, Menu2, Home2 } from '@vicons/tabler'
import { toolsByCategory } from '@/tools';
import SearchBar from '../components/SearchBar.vue';
import { useStyleStore } from '@/stores/style.store';
import HeroGradient from '../assets/hero-gradient.svg?component'
import { useThemeVars } from 'naive-ui'
+import MenuLayout from '../components/MenuLayout.vue'
const themeVars = useThemeVars()
-const collapsed = ref(false)
const activeKey = ref(null)
const route = useRoute()
const styleStore = useStyleStore()
@@ -32,10 +32,9 @@ const m = toolsByCategory.map(category => ({
</script>
<template>
- <n-layout has-sider>
- <n-layout-sider bordered collapse-mode="width" :collapsed-width="64" :width="260" :collapsed="collapsed"
- @collapse="collapsed = true" @expand="collapsed = false" :show-trigger="false" :native-scrollbar="false">
+ <menu-layout class="menu-layout" :class="{ isSmallScreen: styleStore.isSmallScreen }">
+ <template v-slot:sider>
<router-link to="/" class="hero-wrapper">
<hero-gradient class="gradient" />
<div class="text-wrapper">
@@ -45,34 +44,72 @@ const m = toolsByCategory.map(category => ({
</div>
</router-link>
- <n-menu :value="route.name" class="menu" :collapsed="collapsed" :collapsed-width="64"
- :collapsed-icon-size="22" :options="m" v-model:value="activeKey" />
+ <div class="sider-content">
+ <n-space v-if="styleStore.isSmallScreen" justify="center">
+ <n-button size="large" circle quaternary tag="a" href="https://github.com/CorentinTh/it-tools"
+ rel="noopener" target="_blank">
+ <n-icon size="25" :component="BrandGithub" />
+ </n-button>
+ <n-button size="large" circle quaternary tag="a" href="https://twitter.com/cthmsst" rel="noopener"
+ target="_blank">
+ <n-icon size="25" :component="BrandTwitter" />
+ </n-button>
+ <n-button size="large" circle quaternary @click="styleStore.isDarkTheme = !styleStore.isDarkTheme">
+ <n-icon size="25" v-if="styleStore.isDarkTheme" :component="Sun" />
+ <n-icon size="25" v-else :component="Moon" />
+ </n-button>
+ </n-space>
+
+ <n-menu :value="route.name" class="menu" :collapsed-width="64" :collapsed-icon-size="22" :options="m"
+ v-model:value="activeKey" :indent="20" />
+
+ </div>
+
+
+ </template>
+
+ <template v-slot:content>
+ <div class="navigation">
+ <n-button :size="styleStore.isSmallScreen ? 'medium' : 'large'" circle quaternary
+ @click="styleStore.isMenuCollapsed = !styleStore.isMenuCollapsed">
+ <n-icon size="25" :component="Menu2" />
+ </n-button>
+
+ <router-link to="/" #="{ navigate, href }" custom>
+ <n-button tag="a" :href="href" @click="navigate"
+ :size="styleStore.isSmallScreen ? 'medium' : 'large'" circle quaternary>
+ <n-icon size="25" :component="Home2" />
+ </n-button>
+ </router-link>
- </n-layout-sider>
- <n-layout class="content">
- <div class="bar-wrapper">
<search-bar />
+
+
<n-button type="primary" tag="a" href="https://github.com/sponsors/CorentinTh" rel="noopener"
target="_blank">
- <n-icon :component="Heart" />&nbsp;
+ <n-icon :component="Heart" style="margin-right: 5px;" v-if="!styleStore.isSmallScreen" />
Sponsor
</n-button>
<n-button size="large" circle quaternary tag="a" href="https://github.com/CorentinTh/it-tools"
- rel="noopener" target="_blank">
+ rel="noopener" target="_blank" v-if="!styleStore.isSmallScreen">
<n-icon size="25" :component="BrandGithub" />
</n-button>
<n-button size="large" circle quaternary tag="a" href="https://twitter.com/cthmsst" rel="noopener"
- target="_blank">
+ target="_blank" v-if="!styleStore.isSmallScreen">
<n-icon size="25" :component="BrandTwitter" />
</n-button>
- <n-button size="large" circle quaternary @click="styleStore.isDarkTheme = !styleStore.isDarkTheme">
+ <n-button size="large" circle quaternary @click="styleStore.isDarkTheme = !styleStore.isDarkTheme"
+ v-if="!styleStore.isSmallScreen">
<n-icon size="25" v-if="styleStore.isDarkTheme" :component="Sun" />
<n-icon size="25" v-else :component="Moon" />
</n-button>
+
</div>
<slot />
- </n-layout>
- </n-layout>
+
+ </template>
+
+ </menu-layout>
</template>
<style lang="less" scoped>
@@ -87,7 +124,7 @@ const m = toolsByCategory.map(category => ({
// background-size: @size @size;
// }
-.n-menu {
+.sider-content {
padding-top: 160px;
padding-bottom: 200px;
}
@@ -99,9 +136,10 @@ const m = toolsByCategory.map(category => ({
left: 0;
width: 100%;
z-index: 10;
+ overflow: hidden;
.gradient {
- margin-top: -80px;
+ margin-top: -65px;
}
.text-wrapper {
@@ -131,29 +169,24 @@ const m = toolsByCategory.map(category => ({
}
}
-.bar-wrapper {
+.navigation {
display: flex;
align-items: center;
justify-content: center;
+ flex-direction: row;
&>*:not(:first-child) {
- margin-left: 15px;
- }
+ margin-left: 10px;
- .search-bar {
- flex-grow: 1;
+ .isSmallScreen & {
+ margin-left: 5px;
+ }
}
-}
-.content {
- // background-color: #f1f5f9;
- ::v-deep(.n-layout-scroll-container) {
- padding: 26px;
+ .search-bar {
+ // width: 100%;
+ flex-grow: 1;
}
}
-
-.n-layout {
- height: 100vh;
-}
</style> \ No newline at end of file
diff --git a/src/layouts/tool.layout.vue b/src/layouts/tool.layout.vue
index 01c8cc1..2705a50 100644
--- a/src/layouts/tool.layout.vue
+++ b/src/layouts/tool.layout.vue
@@ -45,19 +45,23 @@ useHead(head)
.tool-header {
padding: 40px 0;
+
.n-h1 {
opacity: 0.9;
font-size: 40px;
font-weight: 400;
margin: 0;
+ line-height: 1;
}
+
.separator {
width: 200px;
height: 2px;
background: rgb(161, 161, 161);
- margin-bottom: 10px;
+ margin: 10px 0;
}
+
.description {
margin: 0;
diff --git a/src/stores/style.store.ts b/src/stores/style.store.ts
index 6026d8b..79c372c 100644
--- a/src/stores/style.store.ts
+++ b/src/stores/style.store.ts
@@ -1,9 +1,11 @@
-import { useStorage } from '@vueuse/core';
+import { useMediaQuery, useStorage } from '@vueuse/core';
import { defineStore } from 'pinia';
import type { Ref } from 'vue';
export const useStyleStore = defineStore('style', {
state: () => ({
- isDarkTheme: useStorage('useDarkTheme', false) as Ref<boolean>,
+ isDarkTheme: useStorage('isDarkTheme', true) as Ref<boolean>,
+ isMenuCollapsed: useStorage('isMenuCollapsed', false) as Ref<boolean>,
+ isSmallScreen: useMediaQuery('(max-width: 700px)'),
}),
});