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",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.6.7",
|
||||
"@jamescoyle/vue-icon": "^0.1.2",
|
||||
"@mdi/js": "^7.0.96",
|
||||
"vue": "^3.2.37",
|
||||
@ -49,6 +50,17 @@
|
||||
"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": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
||||
@ -1618,6 +1630,12 @@
|
||||
"dev": 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": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/vue": "^1.6.7",
|
||||
"@jamescoyle/vue-icon": "^0.1.2",
|
||||
"@mdi/js": "^7.0.96",
|
||||
"vue": "^3.2.37",
|
||||
|
@ -1,13 +1,19 @@
|
||||
<script>
|
||||
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 {Menu, MenuButton, MenuItem, MenuItems} from '@headlessui/vue'
|
||||
export default {
|
||||
name: 'Navbar',
|
||||
components: {
|
||||
mdiMenu,
|
||||
MobileLink,
|
||||
Navlink
|
||||
Navlink,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuItem,
|
||||
MenuItems,
|
||||
SvgIcon
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -24,7 +30,7 @@
|
||||
</script>
|
||||
<template>
|
||||
<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 -->
|
||||
<div class="inline-flex justify-center items-center">
|
||||
<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">
|
||||
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes" :key="route.path" />
|
||||
</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">
|
||||
<span class="menu-toggle-top"></span>
|
||||
<span class="menu-toggle-middle"></span>
|
||||
<span class="menu-toggle-bottom"></span>
|
||||
</button>
|
||||
</div>
|
||||
<Transition
|
||||
enter-active-class="transition-all duration-200 ease-in"
|
||||
enter-from-class="opacity-0 -translate-y-1/3"
|
||||
leave-active-class="transition-all duration-200 ease-out"
|
||||
leave-to-class="opacity-0 -translate-y-1/3"
|
||||
>
|
||||
<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">
|
||||
<MobileLink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes" :key="route.path" @optionSelected="toggleMenu" />
|
||||
<Menu v-slot="{ open }" as="div" class="relative inline-block text-left md:hidden">
|
||||
<div>
|
||||
<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="scale-150">
|
||||
<mdiMenu/>
|
||||
</span>
|
||||
</MenuButton>
|
||||
</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">
|
||||
<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">
|
||||
<div class="py-1">
|
||||
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes" :key="route.path" >
|
||||
<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">
|
||||
<span class="scale-75">
|
||||
<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>
|
||||
</nav>
|
||||
</template>
|
||||
<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