JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<site-navigation></site-navigation>
</div>
SCSS
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
padding: 3em;
#sitenav {
max-width: 90vw;
overflow-x: hidden;
background-color: #ddd;
ul {
list-style-type: none;
display: flex;
align-items: flex-start;
li {
margin-right: 1em;
margin-left: 1em;
}
a {
display: block;
padding: 1em 2em;
text-decoration: none;
white-space: nowrap;
font-size: 1.5rem;
}
.drop-list {
span {
margin-left: 0.25em;
display: inline-block;
transform: rotate(90deg);
font-size: 80%;
}
}
}
}
}
.dropdown {
display: none;
&.isOpen {
display: block;
}
.dropnav {
position: absolute;
display: flex;
flex-flow: column wrap;
background-color: #eee;
}
}
JavaScript
Vue.component('site-navigation', {
data() {
return {
navList: [
{
link: '#',
title: 'Page 1',
},
{
link: '#',
title: 'Page 2',
},
{
link: '#',
title: 'Page 3',
},
{
link: '#',
title: 'Page 4',
children: [
{link: '#', title: 'SubPage'},
{link: '#', title: 'SubPage'},
]
},
{
link: '#',
title: 'Page 5',
},
{
link: '#',
title: 'Page 6',
},
{
link: '#',
title: 'Page 7',
},
],
isOpen: false,
left: 0,
}
},
methods: {
mouseOver() {
this.isOpen = !this.isOpen;
},
onMousemove(e) {
this.left -= e.movementX / 10;
},
},
template: `
<nav id="sitenav" @mousemove="onMousemove" :style="{ transform: \`translateX(\${left}px)\` }">
<ul>
<li v-for="list in navList">
<template v-if="list.children" :class="{ active }">
<a class="drop-list" :href="list.link" :title="list.title" @click="isOpen = !isOpen">{{ list.title }} <span>></span></a>
<div class="dropdown" :class="{ isOpen }" @mouseover="isOpen = true" @mouseleave="isOpen = false">
<ul class="dropnav">
<li v-for="{ link, title, index, target } in list.children" :key="index">
<a class="transition" :href="link" :title="title">{{ title }}
</li>
</ul>
</div>
</template>
<template v-else>
<a class="transition" :href="list.link" :title="list.title">{{ list.title }}</a>
</template>
</li>
</ul>
</nav>
`,
});
new Vue({
el: '#app',
})