Untitled
unknown
jsx
2 years ago
4.3 kB
2
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