Untitled

mail@pastecode.io avatar
unknown
jsx
7 months ago
4.3 kB
0
Indexable
Never
<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>
Leave a Comment