project nearly finished. TODO Next : Project page and refine some text
This commit is contained in:
370
src/components/Menu.vue
Normal file
370
src/components/Menu.vue
Normal file
@@ -0,0 +1,370 @@
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('scroll', onScroll)
|
||||
|
||||
const allLinks = document.querySelectorAll('a')
|
||||
for (const a of allLinks){
|
||||
a.addEventListener('mouseleave', () => {
|
||||
if (a.classList[1] != 'router-link-exact-active'){
|
||||
a.classList.add('hover-out');
|
||||
a.addEventListener('transitionend', () => {
|
||||
a.classList.remove('hover-out')
|
||||
}, {once : true})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const onScroll = () => {
|
||||
const menu = document.querySelector(".menu")
|
||||
const menuYPosition = menu.getBoundingClientRect().y
|
||||
|
||||
//console.log(menu)
|
||||
if (menuYPosition <= 0){
|
||||
document.querySelector('.nav-menu').classList.add('sticked')
|
||||
}
|
||||
else{
|
||||
document.querySelector('.nav-menu').classList.remove('sticked')
|
||||
}
|
||||
}
|
||||
|
||||
const menuOpen = ref(false)
|
||||
const liShow = ref(false)
|
||||
const menuIsClosing = ref(false)
|
||||
|
||||
const closeMenu = () => {
|
||||
menuIsClosing.value = true;
|
||||
menuOpen.value = false;
|
||||
|
||||
const sideBarNav = document.querySelector('.nav-menu')
|
||||
sideBarNav.addEventListener('transitionend', () => {
|
||||
liShow.value = false
|
||||
menuIsClosing.value = false;
|
||||
//if menu is reopen during animation, let show all the li :
|
||||
if (menuOpen.value){
|
||||
liShow.value = true
|
||||
}
|
||||
}, {once : true})
|
||||
}
|
||||
|
||||
const toggleMenu = () => {
|
||||
menuOpen.value = !menuOpen.value;
|
||||
if (menuOpen.value){
|
||||
liShow.value = true
|
||||
}
|
||||
else{
|
||||
closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="menu-container">
|
||||
<div class="burger">
|
||||
<button class="button"
|
||||
@click="toggleMenu()"
|
||||
>
|
||||
<svg class="hamburger"
|
||||
v-bind:class="{open : menuOpen}"
|
||||
viewBox="2 0 100 100">
|
||||
<path
|
||||
class="cross"
|
||||
style="fill:none;
|
||||
stroke-linecap:round;
|
||||
stroke-linejoin:round;
|
||||
stroke-opacity:1"
|
||||
d="M 36,21 H 74 L 74,33 55,52 36,71 36,83 H 74 L 74,71 36,33 Z"
|
||||
id="path978"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
class="middle"
|
||||
style="fill:none;
|
||||
stroke-linecap:round;
|
||||
stroke-linejoin:bevel;
|
||||
stroke-opacity:1"
|
||||
d="M 36,52 H 74 C 90,52 82,69 77,74 71,80 63,83 55,83 38,83 24,69 24,52 24,35 38,21 55,21 c 17,0 31,14 31,31 0,9 -3,16 -9,22"
|
||||
id="path982"
|
||||
sodipodi:nodetypes="cccssssc" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="nav-menu"
|
||||
v-bind:class="{open : menuOpen}"
|
||||
>
|
||||
<li
|
||||
class=""
|
||||
v-bind:class="{show : liShow, closing : menuIsClosing}"
|
||||
@click="closeMenu()">
|
||||
<router-link
|
||||
:to="{name:'whoAmI'}">
|
||||
Who Am I
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
v-bind:class="{show : liShow, closing : menuIsClosing}"
|
||||
@click="closeMenu()">
|
||||
<router-link
|
||||
:to="{name:'technologies'}">
|
||||
Technologies
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
v-bind:class="{show : liShow, closing : menuIsClosing}"
|
||||
@click="closeMenu()">
|
||||
<router-link
|
||||
:to="{name:'projects'}">
|
||||
Projects
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
v-bind:class="{show : liShow, closing : menuIsClosing}"
|
||||
@click="closeMenu()">
|
||||
<router-link
|
||||
:to="{name:'networks'}">
|
||||
Networks
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
v-bind:class="{show : liShow, closing : menuIsClosing}"
|
||||
@click="closeMenu()">
|
||||
<router-link
|
||||
:to="{name:'contact'}">
|
||||
Contact
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../style/shared.scss';
|
||||
|
||||
.burger{
|
||||
display: none;
|
||||
opacity:0;
|
||||
transition:0.5s;
|
||||
& .button{
|
||||
width: 3.5em;
|
||||
// height: 4.5em;
|
||||
background-color:$red-light;
|
||||
border: none;
|
||||
transition:1s ;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
& .hamburger{
|
||||
& .cross, & .middle {
|
||||
stroke-width:7;
|
||||
transition:1s ;
|
||||
stroke:$white;
|
||||
}
|
||||
& .cross{
|
||||
stroke-dashoffset: 0 ;
|
||||
stroke-dasharray: 0 0 36 80 36 80;
|
||||
}
|
||||
|
||||
& .middle{
|
||||
stroke-dashoffset: 0 ;
|
||||
stroke-dasharray: 36 250;
|
||||
}
|
||||
&.open{
|
||||
& .cross{
|
||||
stroke-width:7;
|
||||
stroke-dashoffset: -61 ;
|
||||
stroke-dasharray: 33 82 33 79;
|
||||
}
|
||||
|
||||
& .middle{
|
||||
stroke-width:7;
|
||||
stroke-dashoffset: -60 ;
|
||||
stroke-dasharray: 270 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.nav-menu{
|
||||
//z-index: 999;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1.5em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background-color: rgba(0, 0, 0, 0.233);
|
||||
padding:1rem 0.5rem;
|
||||
//overflow: hidden;
|
||||
//transition: 0.5s;
|
||||
&.sticked{
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
a{
|
||||
font-size:1em;
|
||||
font-family: 'Montserrat', Arial, Helvetica, sans-serif;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color : $white;
|
||||
text-decoration: none;
|
||||
&::after{
|
||||
content: "";
|
||||
background-color: $red-light;
|
||||
width: 0%;
|
||||
margin-left:0;
|
||||
height: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover, &.router-link-exact-active{
|
||||
color:$red-light;
|
||||
transition: color 0.25s;
|
||||
cursor: pointer;
|
||||
}
|
||||
&.router-link-exact-active{
|
||||
filter: drop-shadow(0 0 4px $red-light);
|
||||
transition: filter 0.3s;
|
||||
}
|
||||
&:hover::after, &.router-link-exact-active::after{
|
||||
width: 100%;
|
||||
//This transition fires on the hover
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
&.hover-out::after{
|
||||
margin-left:100%;
|
||||
//This transition fires on hover-out class
|
||||
transition:0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
transform: translateY(1.25em);
|
||||
opacity:0;
|
||||
overflow: hidden;
|
||||
@for $i from 1 to 6 {
|
||||
&:nth-child(#{$i}){
|
||||
animation: 250ms theMenu (100 * $i - 0ms) ease forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (width < 750px ){
|
||||
nav.menu-container{
|
||||
//border: $white solid 3px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
& .burger{
|
||||
margin-bottom: 1.5em;
|
||||
display: block;
|
||||
position: sticky;
|
||||
top:0;
|
||||
opacity: 0;
|
||||
z-index:9999;
|
||||
animation: burger 0.5s ease-in-out forwards;
|
||||
}
|
||||
& > ul.nav-menu{
|
||||
position:fixed;
|
||||
top:0;
|
||||
bottom:0;
|
||||
|
||||
z-index: 99;
|
||||
right:-250px;
|
||||
transform: translateX(0%);
|
||||
margin-top:0;
|
||||
margin-bottom: 0;
|
||||
width: 250px;
|
||||
background: hsl(0 0% 0% / 0.95);
|
||||
transition: 0.5s ease-out;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
padding-right: 1em;
|
||||
text-align: right;
|
||||
&.open{
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
& > li{
|
||||
display: none;
|
||||
opacity:0;
|
||||
}
|
||||
& > li.show{
|
||||
display: block;
|
||||
transform: translateY(1.25em);
|
||||
@for $i from 1 to 6 {
|
||||
&:nth-child(#{$i}){
|
||||
animation: 250ms theMenu (80 * $i + 0ms) ease-out forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > li.closing {
|
||||
transform: translateY(0em);
|
||||
opacity: 1;
|
||||
@for $i from 1 to 6 {
|
||||
&:nth-child(#{$i}){
|
||||
//animation in reverse side...
|
||||
animation: 150ms closeMe ( 50ms * (5 - $i)) ease-out forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > li > a {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@supports (backdrop-filter: blur(0.5rem)){
|
||||
nav.menu-container > ul.nav-menu{
|
||||
background-color: hsla(0, 100%, 0%, 0.25);
|
||||
backdrop-filter: blur(0.5rem);
|
||||
/* adding backdrop-filter compatibility for firefox and safari */
|
||||
-webkit-backdrop-filter: blur(0.6rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (height < 650px) and (width < 750px) {
|
||||
div.menu-container .burger{
|
||||
position : fixed;
|
||||
top:0;
|
||||
right:0;
|
||||
}
|
||||
}
|
||||
@keyframes burger {
|
||||
100%{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes theMenu{
|
||||
100%{
|
||||
transform: translateY(0);
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
@keyframes closeMe{
|
||||
100%{
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes border-hover {
|
||||
0%{
|
||||
border-bottom: none;
|
||||
border-width: 0%;
|
||||
}
|
||||
100%{
|
||||
border-width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user