Added About Page

This commit is contained in:
2025-09-17 23:34:37 +10:00
parent 2f6006626d
commit b9e1f6827a
30 changed files with 1270 additions and 529 deletions

View File

@@ -3,29 +3,25 @@
<header class="header">
<section class="navContainer">
<nav class="nav">
<div class="nav-brand">Dr Edgy Adventures</div>
<div class="nav-brand">
<Link href="/">
<img src="/img/logos/logo_main.png" alt="Dr Edgy Logo" style="height:5vh; width:auto;" />
</Link>
</div>
<button class="mobile-menu-btn">
<span></span><span></span><span></span>
</button>
</nav>
<div class="nav-menu">
<a href="/about" class="nav-link">About</a>
<a href="#contact" class="nav-link">Contact</a>
<div
class="dropdown"
:class="{ open: dropdownOpen }"
>
<Link href="/about" @click="dropdownOpen = false" class="nav-link">About</Link>
<div class="dropdown" ref="dropdownRef" :class="{ open: dropdownOpen }">
<button
class="dropdown-toggle nav-link"
@click="dropdownOpen = !dropdownOpen"
@click.stop="dropdownOpen = !dropdownOpen"
>
Adventures
<svg
class="dropdown-icon"
width="16" height="16" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2"
>
<svg class="dropdown-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
</button>
@@ -47,36 +43,52 @@
<script setup lang="ts">
import { onMounted, onUnmounted, computed, ref } from 'vue';
import { usePage} from "@inertiajs/vue3";
import {GlobalProperties} from "@/types";
import { usePage } from "@inertiajs/vue3";
import { GlobalProperties } from "@/types";
import { Link } from '@inertiajs/vue3';
const { continents_with_tours } = usePage().props as unknown as GlobalProperties
const { continents_with_tours } = usePage().props as unknown as GlobalProperties;
const dropdownOpen = ref(false)
const dropdownOpen = ref(false);
const windowWidth = ref(window.innerWidth);
const dropdownRef = ref<HTMLElement | null>(null);
onMounted(() =>{
initDropdown();
initHeaderScroll()
initMobileMenu()
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
const isDropdownVisible = computed(() => {
return dropdownOpen.value || windowWidth.value < 768;
});
const isDropdownVisible = computed(() => dropdownOpen.value || windowWidth.value < 768);
const handleResize = () => {
windowWidth.value = window.innerWidth;
};
// Close when clicking outside (desktop only)
const handleClickOutside = (e: Event) => {
if (!dropdownRef.value) return;
if (windowWidth.value < 768) return; // on mobile we show inline; skip closing here
// Support composedPath for shadow DOM correctness
const path = (e as MouseEvent).composedPath?.();
const clickedInside = path ? path.includes(dropdownRef.value) : dropdownRef.value.contains(e.target as Node);
if (!clickedInside) {
dropdownOpen.value = false;
}
};
const handleEsc = (e: KeyboardEvent) => {
if (e.key === 'Escape') dropdownOpen.value = false;
};
onMounted(() => {
initMobileMenu(); // keep your mobile menu init
window.addEventListener('resize', handleResize);
document.addEventListener('click', handleClickOutside);
document.addEventListener('keydown', handleEsc);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
document.removeEventListener('click', handleClickOutside);
document.removeEventListener('keydown', handleEsc);
});
// Mobile menu functionality
const initMobileMenu = (): void => {
@@ -85,50 +97,21 @@ const initMobileMenu = (): void => {
if (!mobileMenuBtn || !navMenu) return;
// Toggle menu open/close
mobileMenuBtn.addEventListener('click', () => {
navMenu.classList.toggle('open');
mobileMenuBtn.classList.toggle('open');
});
};
// Header background on scroll
const initHeaderScroll = (): void => {
const header = document.querySelector('.header') as HTMLElement | null;
if (!header) return;
window.addEventListener('scroll', () => {
if (window.scrollY > 100) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
// Close menu when a link is clicked
navMenu.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', () => {
navMenu.classList.remove('open');
mobileMenuBtn.classList.remove('open');
});
});
};
const initDropdown = (): void => {
const dropdown = document.querySelector('.dropdown') as HTMLElement | null;
const dropdownToggle = dropdown?.querySelector('.dropdown-toggle') as HTMLElement | null;
if (!dropdown || !dropdownToggle) return;
dropdownToggle.addEventListener('click', (e: Event) => {
e.preventDefault();
dropdown.classList.toggle('open');
});
// Close dropdown when clicking outside
document.addEventListener('click', (e: Event) => {
if (!dropdown.contains(e.target as Node)) {
dropdown.classList.remove('open');
}
});
document.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape') {
dropdown.classList.remove('open');
}
});
};
</script>
<style scoped>
@@ -208,20 +191,9 @@ const initDropdown = (): void => {
align-items: center;
justify-content: space-between;
width: 100%;
padding: 1em;
/* padding / width handled in the desktop guard above */
}
/* brand */
.nav-brand {
font-size: 1.5rem;
font-weight: bold;
background: var(--gradient-adventure);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* links container (desktop default) */
.nav-menu {
display: flex;
@@ -359,6 +331,8 @@ const initDropdown = (): void => {
overflow-y: auto;
}
.nav-menu.open {
transform: translateY(0);
opacity: 1;
@@ -370,6 +344,20 @@ const initDropdown = (): void => {
font-size: 1.5rem;
}
.nav-brand {
position:relative;
padding: 1em;
display: flex;
align-items: center;
justify-content: center;
width: 90dvw;
}
.nav-brand img {
display: block;
margin-left: calc(10dvw / 2);
}
/* Dropdown in mobile: behave as inline sublist */
.dropdown {
width: 100%;
@@ -408,6 +396,7 @@ const initDropdown = (): void => {
.mobile-menu-btn {
display: flex;
width: 10dvw;
}
}
</style>