|
|
@@ -1,30 +1,105 @@
|
|
|
<template>
|
|
|
- <header class="absolute top-7 center-0 z-50 bg-black/60">
|
|
|
- <nav class="w-full flex items-center justify-center h-[55px] px-4">
|
|
|
+ <header ref="headerRef" class="w-9/10 lg:w-auto absolute top-7 center-0 z-50 bg-black/80 lg:bg-black/60">
|
|
|
+ <nav class="flex items-center justify-center h-[55px] px-4 relative">
|
|
|
+ <div class="hidden md:flex items-center justify-center gap-1">
|
|
|
+ <NuxtLink
|
|
|
+ v-for="item in navItems"
|
|
|
+ :key="item.label"
|
|
|
+ :to="item.href"
|
|
|
+ class="relative text-xs font-open-sans font-semibold px-3 uppercase transition-colors duration-200 pb-1 leading-7"
|
|
|
+ :class="[
|
|
|
+ activeSection === item.href.slice(1)
|
|
|
+ ? 'text-[#E3FA6D] after:absolute after:bottom-0 after:left-0 after:w-full after:h-0.5 after:bg-[#E3FA6D]'
|
|
|
+ : 'text-white hover:text-white/85'
|
|
|
+ ]"
|
|
|
+ >
|
|
|
+ {{ item.label }}
|
|
|
+ </NuxtLink>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <NuxtLink to="#hero" class="md:hidden absolute left-4">
|
|
|
+ <NuxtImg src="/img/logo_2.png" class="h-9 w-auto object-contain" />
|
|
|
+ </NuxtLink>
|
|
|
+
|
|
|
+ <button
|
|
|
+ class="md:hidden absolute right-4 text-white focus:outline-none"
|
|
|
+ aria-label="Abrir menu"
|
|
|
+ @click.stop="menuOpen = !menuOpen"
|
|
|
+ >
|
|
|
+ <svg v-if="!menuOpen" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
|
+ </svg>
|
|
|
+ <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+ </nav>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-if="menuOpen"
|
|
|
+ class="md:hidden flex flex-col items-center py-4 gap-4"
|
|
|
+ >
|
|
|
<NuxtLink
|
|
|
v-for="item in navItems"
|
|
|
:key="item.label"
|
|
|
:to="item.href"
|
|
|
- class="relative text-xs font-open-sans font-semibold px-3 uppercase transition-colors duration-200 pb-1 leading-7"
|
|
|
+ class="relative text-xs font-open-sans font-semibold uppercase transition-colors duration-200"
|
|
|
:class="[
|
|
|
- item.active
|
|
|
- ? 'text-[#E3FA6D] after:absolute after:bottom-0 after:left-0 after:w-full after:h-0.5 after:bg-[#E3FA6D]'
|
|
|
+ activeSection === item.href.slice(1)
|
|
|
+ ? 'text-[#E3FA6D]'
|
|
|
: 'text-white hover:text-white/85'
|
|
|
]"
|
|
|
+ @click="menuOpen = false"
|
|
|
>
|
|
|
{{ item.label }}
|
|
|
</NuxtLink>
|
|
|
- </nav>
|
|
|
+ </div>
|
|
|
</header>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
+const menuOpen = ref(false)
|
|
|
+const headerRef = ref<HTMLElement | null>(null)
|
|
|
+const activeSection = ref('hero')
|
|
|
+
|
|
|
const navItems = [
|
|
|
- { label: 'Home', href: '#hero', active: true },
|
|
|
- { label: 'A Imersão', href: '#imersao', active: false },
|
|
|
- { label: 'Metodologia', href: '#metodologia', active: false },
|
|
|
- { label: 'Executores', href: '#executores', active: false },
|
|
|
- { label: 'Próximos Destinos', href: '#destinos', active: false },
|
|
|
- { label: 'Contato', href: '#contato', active: false },
|
|
|
+ { label: 'Home', href: '#hero' },
|
|
|
+ { label: 'A Imersão', href: '#imersao' },
|
|
|
+ { label: 'Metodologia', href: '#metodologia' },
|
|
|
+ { label: 'Executores', href: '#executores' },
|
|
|
+ { label: 'Próximos Destinos', href: '#destinos' },
|
|
|
+ { label: 'Contato', href: '#contato' },
|
|
|
]
|
|
|
+
|
|
|
+function handleClickOutside(event: MouseEvent) {
|
|
|
+ if (menuOpen.value && headerRef.value && !headerRef.value.contains(event.target as Node)) {
|
|
|
+ menuOpen.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ document.addEventListener('click', handleClickOutside)
|
|
|
+
|
|
|
+ const sectionIds = navItems.map(i => i.href.slice(1))
|
|
|
+ const observer = new IntersectionObserver(
|
|
|
+ (entries) => {
|
|
|
+ for (const entry of entries) {
|
|
|
+ if (entry.isIntersecting) {
|
|
|
+ activeSection.value = entry.target.id
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { threshold: 0.3 }
|
|
|
+ )
|
|
|
+
|
|
|
+ sectionIds.forEach(id => {
|
|
|
+ const el = document.getElementById(id)
|
|
|
+ if (el) observer.observe(el)
|
|
|
+ })
|
|
|
+
|
|
|
+ onUnmounted(() => {
|
|
|
+ document.removeEventListener('click', handleClickOutside)
|
|
|
+ observer.disconnect()
|
|
|
+ })
|
|
|
+})
|
|
|
</script>
|