Untitled
unknown
jsx
2 years ago
4.3 kB
5
Indexable
<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, defineProps } from 'vue';
import NavigationLink from './NavigationLink.vue';
interface NavLink {
text: string;
url: string;
isCta: boolean;
}
const props = defineProps({
links: {
type: Array as () => NavLink[],
required: true,
},
darkTheme: {
type: Boolean,
default: false,
},
});
const isOpen = ref(false);
const drawer = () => {
isOpen.value = !isOpen.value;
};
const closeDrawerOnEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isOpen.value) {
isOpen.value = false;
}
};
watch(isOpen, (val) => {
if (process.client) {
document.body.style.overflow = val ? 'hidden' : '';
}
});
onMounted(() => {
document.addEventListener('keydown', closeDrawerOnEscape);
});
onBeforeUnmount(() => {
document.removeEventListener('keydown', closeDrawerOnEscape);
});
</script>
<template>
<nav
:class="{ 'bg-slate-800': darkTheme, 'bg-transparent': !darkTheme }"
class="fixed w-full p-6"
>
<div class="flex items-center justify-between">
<!-- Header logo -->
<div class="text-md" :class="{ 'text-white': darkTheme }">
Frosh Digital
</div>
<!-- Mobile toggle -->
<div class="md:hidden flex">
<button @click="drawer">
<svg
class="h-8 w-8 fill-current"
:class="{ 'text-white': darkTheme, 'text-black': !darkTheme }"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path d="M4 6h16M4 12h16M4 18h16"></path>
</svg>
</button>
</div>
<!-- Navbar -->
<div class="hidden md:block">
<ul class="flex space-x-8 text-md font-sans items-center">
<NavigationLink
v-for="(link, index) in links"
:key="index"
:link="link"
:index="index"
:currentLinkIndex="0"
:cta-link="link.isCta || undefined"
:dark-theme="darkTheme"
/>
</ul>
</div>
<!-- Dark Background Transition -->
<transition
enter-class="opacity-0"
enter-active-class="ease-out transition-medium"
enter-to-class="opacity-100"
leave-class="opacity-100"
leave-active-class="ease-out transition-medium"
leave-to-class="opacity-0"
>
<div
@keydown.esc="isOpen = false"
v-show="isOpen"
class="z-10 fixed inset-0 transition-opacity"
>
<div
@click="isOpen = false"
class="absolute inset-0 bg-black opacity-50"
tabindex="0"
></div>
</div>
</transition>
<!-- Drawer Menu -->
<aside
class="p-5 transform top-0 left-0 w-64 fixed h-full overflow-auto ease-in-out transition-all duration-300 z-30"
:class="{
'translate-x-0': isOpen,
'-translate-x-full': !isOpen,
'bg-white': !darkTheme,
'bg-slate-900': darkTheme,
}"
>
<div class="close">
<button
class="absolute top-0 right-0 mt-4 mr-4"
@click="isOpen = false"
>
<svg
class="w-6 h-6"
fill="'none'"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
:stroke="darkTheme ? 'white' : 'currentColor'"
>
<path d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<span
@click="isOpen = false"
class="flex w-full items-center p-4 border-b"
>
<Tailwind />
</span>
<!-- Mobile nav -->
<ul class="divide-y font-sans">
<NavigationLink
v-for="(link, index) in links"
:key="index"
:link="link"
:index="index"
:cta-link="link.isCta || undefined"
:dark-theme="darkTheme"
:is-mobile="true"
/>
</ul>
</aside>
</div>
</nav>
</template>
Editor is loading...
Leave a Comment