Incorporated headlessui/vue
Made a better accessible collapsed menu
This commit is contained in:
parent
c63ace6f08
commit
66e30eaf69
18
client/package-lock.json
generated
18
client/package-lock.json
generated
@ -8,6 +8,7 @@
|
|||||||
"name": "client",
|
"name": "client",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@headlessui/vue": "^1.6.7",
|
||||||
"@jamescoyle/vue-icon": "^0.1.2",
|
"@jamescoyle/vue-icon": "^0.1.2",
|
||||||
"@mdi/js": "^7.0.96",
|
"@mdi/js": "^7.0.96",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
@ -49,6 +50,17 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@headlessui/vue": {
|
||||||
|
"version": "1.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.6.7.tgz",
|
||||||
|
"integrity": "sha512-5sTCBpkUoFE7zhANn/6Z+pf3PUA7MD6BBaTsJcQybq9E4fnNiMM9agOJI9meXbtcawE6Dm8EeB5A8HAJEnZCbQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jamescoyle/vue-icon": {
|
"node_modules/@jamescoyle/vue-icon": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
||||||
@ -1618,6 +1630,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@headlessui/vue": {
|
||||||
|
"version": "1.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.6.7.tgz",
|
||||||
|
"integrity": "sha512-5sTCBpkUoFE7zhANn/6Z+pf3PUA7MD6BBaTsJcQybq9E4fnNiMM9agOJI9meXbtcawE6Dm8EeB5A8HAJEnZCbQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@jamescoyle/vue-icon": {
|
"@jamescoyle/vue-icon": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@headlessui/vue": "^1.6.7",
|
||||||
"@jamescoyle/vue-icon": "^0.1.2",
|
"@jamescoyle/vue-icon": "^0.1.2",
|
||||||
"@mdi/js": "^7.0.96",
|
"@mdi/js": "^7.0.96",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
<script>
|
<script>
|
||||||
import mdiMenu from '@/components/icons/Menu.vue'
|
import mdiMenu from '@/components/icons/Menu.vue'
|
||||||
import MobileLink from '@/components/navbar/MobileLink.vue'
|
import SvgIcon from '@jamescoyle/vue-icon'
|
||||||
import Navlink from '@/components/navbar/Navlink.vue'
|
import Navlink from '@/components/navbar/Navlink.vue'
|
||||||
|
import {Menu, MenuButton, MenuItem, MenuItems} from '@headlessui/vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'Navbar',
|
name: 'Navbar',
|
||||||
components: {
|
components: {
|
||||||
mdiMenu,
|
mdiMenu,
|
||||||
MobileLink,
|
MobileLink,
|
||||||
Navlink
|
Navlink,
|
||||||
|
Menu,
|
||||||
|
MenuButton,
|
||||||
|
MenuItem,
|
||||||
|
MenuItems,
|
||||||
|
SvgIcon
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -24,7 +30,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<nav class="fixed bg-lime-900 text-white shadow-xl w-full z-50">
|
<nav class="fixed bg-lime-900 text-white shadow-xl w-full z-50">
|
||||||
<div class="flex relative px-2 max-w-5xl mx-auto items-center justify-between z-50">
|
<div class="flex relative px-2 max-w-5xl mx-auto items-center justify-between">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<div class="inline-flex justify-center items-center">
|
<div class="inline-flex justify-center items-center">
|
||||||
<img src="@/assets/vue.svg" class="p-2" alt="Vite Logo" >
|
<img src="@/assets/vue.svg" class="p-2" alt="Vite Logo" >
|
||||||
@ -34,22 +40,40 @@
|
|||||||
<div class="hidden md:flex space-x-3 justify-center items-center">
|
<div class="hidden md:flex space-x-3 justify-center items-center">
|
||||||
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes" :key="route.path" />
|
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes" :key="route.path" />
|
||||||
</div>
|
</div>
|
||||||
<button id="menu-btn" title="Toggle Menu" aria-title="Toggle Menu" class="block focus:ring relative menu-toggle md:hidden focus:outline-none" :class="{'menu-active': menuActive}" @click="toggleMenu">
|
<Menu v-slot="{ open }" as="div" class="relative inline-block text-left md:hidden">
|
||||||
<span class="menu-toggle-top"></span>
|
<div>
|
||||||
<span class="menu-toggle-middle"></span>
|
<MenuButton class="inline-flex justify-center w-full rounded-md shadow-sm px-4 py-2 bg-lime-800 text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500">
|
||||||
<span class="menu-toggle-bottom"></span>
|
<span class="scale-150">
|
||||||
</button>
|
<mdiMenu/>
|
||||||
|
</span>
|
||||||
|
</MenuButton>
|
||||||
</div>
|
</div>
|
||||||
<Transition
|
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
|
||||||
enter-active-class="transition-all duration-200 ease-in"
|
<MenuItems class="origin-top-right absolute right-0 mt-2 p-1 space-y-2 w-56 rounded-md shadow-lg bg-lime-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
enter-from-class="opacity-0 -translate-y-1/3"
|
<div class="py-1">
|
||||||
leave-active-class="transition-all duration-200 ease-out"
|
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes" :key="route.path" >
|
||||||
leave-to-class="opacity-0 -translate-y-1/3"
|
<a :href="route.path" target="_blank" rel="noopener noreferrer" :class="[active ? 'text-orange-300' : 'text-white', 'flex px-4 py-2 active:text-orange-500 rounded-lg h-fit align-middle transition-all ease-in-out duration-500']" v-if="route.path.startsWith('http')">
|
||||||
>
|
<div class="inline-flex px-3 py-1 space-x-1">
|
||||||
<div id="mobile-nav" class="z-0 w-full bg-lime-700 p-2 space-y-1 absolute flex-col self-end self-center font-bold drop-shadow-md flex md:hidden" v-if="menuActive">
|
<span class="scale-75">
|
||||||
<MobileLink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes" :key="route.path" @optionSelected="toggleMenu" />
|
<svg-icon type="mdi" :path="route.meta.svgPath"></svg-icon>
|
||||||
|
</span>
|
||||||
|
<span>{{ route.meta.title }}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<router-link :to="route.path" :class="[active ? 'text-white bg-lime-600' : 'text-white', 'flex px-4 py-2 active:text-orange-500 rounded-lg h-fit align-middle transition-all ease-in-out duration-500', this.$route.fullPath == route.path ? 'bg-orange-500 text-white hover:bg-orange-600 hover:text-white' : '']" v-else>
|
||||||
|
<div class="inline-flex px-3 py-1 space-x-1">
|
||||||
|
<span class="scale-75">
|
||||||
|
<svg-icon type="mdi" :path="route.meta.svgPath"></svg-icon>
|
||||||
|
</span>
|
||||||
|
<span>{{ route.meta.title }}</span>
|
||||||
|
</div>
|
||||||
|
</router-link>
|
||||||
|
</MenuItem>
|
||||||
|
</div>
|
||||||
|
</MenuItems>
|
||||||
|
</transition>
|
||||||
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
<script>
|
|
||||||
import SvgIcon from '@jamescoyle/vue-icon'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "MobileLink",
|
|
||||||
components: {
|
|
||||||
SvgIcon
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
optionSelected() {
|
|
||||||
this.$emit('optionSelected')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
props: [
|
|
||||||
"svgPath",
|
|
||||||
"text",
|
|
||||||
"to"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<a :href="to" class="navlink w-full" target="_blank" rel="noopener noreferrer" v-if="to.startsWith('http')" v-on:click="optionSelected">
|
|
||||||
<div class="inline-flex px-3 py-1 space-x-1">
|
|
||||||
<span class="scale-75">
|
|
||||||
<svg-icon type="mdi" :path="svgPath"></svg-icon>
|
|
||||||
</span>
|
|
||||||
<span>{{ text }}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div class="relative flex" v-else>
|
|
||||||
<router-link active-class="active-link" class="navlink w-full" :to="to" v-on:click="optionSelected">
|
|
||||||
<div class="inline-flex px-3 py-1 space-x-1">
|
|
||||||
<span class="scale-75">
|
|
||||||
<svg-icon type="mdi" :path="svgPath"></svg-icon>
|
|
||||||
</span>
|
|
||||||
<span>{{ text }}</span>
|
|
||||||
</div>
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style scoped>
|
|
||||||
.navlink.active-link, .navlink.exact-active-link {
|
|
||||||
@apply bg-orange-500;
|
|
||||||
@apply text-white;
|
|
||||||
@apply hover:bg-orange-600;
|
|
||||||
@apply hover:text-white;
|
|
||||||
}
|
|
||||||
.navlink {
|
|
||||||
@apply hover:text-orange-300;
|
|
||||||
@apply active:text-orange-500;
|
|
||||||
@apply rounded-lg;
|
|
||||||
@apply h-fit;
|
|
||||||
@apply align-middle;
|
|
||||||
@apply transition-all;
|
|
||||||
@apply ease-in-out;
|
|
||||||
@apply duration-500;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue
Block a user