259 lines
10 KiB
Plaintext
259 lines
10 KiB
Plaintext
---
|
|
import { NAVIGATION } from '../site.config';
|
|
import ThemeToggle from './ThemeToggle.astro';
|
|
import LanguageSwitcher from './LanguageSwitcher.astro';
|
|
import { getLangFromUrl, useTranslations, localizePath } from '../utils/i18n';
|
|
|
|
const lang = getLangFromUrl(Astro.url);
|
|
const t = await useTranslations(lang);
|
|
---
|
|
|
|
<header class="fixed top-0 left-0 right-0 z-50 transition-all duration-500" id="main-header">
|
|
<!-- Glass morphism navigation -->
|
|
<nav class="nav-glass">
|
|
<div class="container-custom">
|
|
<div class="flex h-20 items-center justify-between">
|
|
|
|
<!-- Logo with modern styling -->
|
|
<div class="flex items-center">
|
|
<a href={localizePath("/", lang)} class="group flex items-center space-x-3 transition-all">
|
|
<div class="relative">
|
|
<div class="absolute inset-0 bg-primary/20 rounded-xl blur-md opacity-0 group-hover:opacity-100 transition-opacity"></div>
|
|
<div class="relative h-10 w-10 bg-gradient-to-br from-primary to-accent rounded-xl flex items-center justify-center">
|
|
<img
|
|
src="/images/TIBER365.png"
|
|
alt="Tiber365 Logo"
|
|
class="h-6 w-6 object-contain brightness-0 invert"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-col">
|
|
<span class="font-bold text-lg text-foreground group-hover:text-primary transition-colors">Tiber365</span>
|
|
<span class="text-xs text-subtle -mt-1">IT Excellence</span>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Desktop Navigation with modern hover effects -->
|
|
<div class="hidden lg:flex items-center space-x-1">
|
|
{NAVIGATION.map((item) => (
|
|
<a
|
|
href={item.type === 'external' ? item.href : localizePath(item.href, lang)}
|
|
target={item.type === 'external' ? '_blank' : undefined}
|
|
rel={item.type === 'external' ? 'noopener noreferrer' : undefined}
|
|
class="relative px-4 py-2 text-sm font-medium text-muted hover:text-foreground transition-all duration-300 rounded-lg group"
|
|
>
|
|
<span class="relative z-10 flex items-center gap-1">
|
|
{t(item.label)}
|
|
{item.type === 'external' && (
|
|
<svg class="h-3 w-3 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
|
</svg>
|
|
)}
|
|
</span>
|
|
<!-- Hover background -->
|
|
<div class="absolute inset-0 bg-surface/50 rounded-lg opacity-0 group-hover:opacity-100 transition-all duration-300 scale-95 group-hover:scale-100"></div>
|
|
<!-- Active indicator -->
|
|
<div class="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-0 h-0.5 bg-gradient-to-r from-primary to-accent group-hover:w-full transition-all duration-300"></div>
|
|
</a>
|
|
))}
|
|
|
|
<!-- CTA Button in nav -->
|
|
<a
|
|
href={localizePath("/contact", lang)}
|
|
class="ml-4 btn btn-primary btn-sm"
|
|
>
|
|
Get Started
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Right side controls -->
|
|
<div class="flex items-center space-x-3">
|
|
<!-- Language switcher with modern styling -->
|
|
<LanguageSwitcher />
|
|
|
|
<!-- Theme toggle with modern animation -->
|
|
<ThemeToggle />
|
|
|
|
<!-- Mobile Menu Button -->
|
|
<button
|
|
id="mobile-menu-button"
|
|
class="lg:hidden p-2 rounded-xl bg-surface/50 border border-border/50 text-muted hover:text-foreground hover:bg-surface transition-all"
|
|
aria-expanded="false"
|
|
aria-label="Toggle mobile menu"
|
|
>
|
|
<svg id="mobile-menu-icon" class="h-5 w-5 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
|
|
</svg>
|
|
<svg id="mobile-close-icon" class="h-5 w-5 hidden transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Navigation Menu -->
|
|
<div id="mobile-menu" class="lg:hidden hidden border-t border-border/50">
|
|
<div class="container-custom py-6">
|
|
<div class="space-y-2">
|
|
{NAVIGATION.map((item) => (
|
|
<a
|
|
href={item.type === 'external' ? item.href : localizePath(item.href, lang)}
|
|
target={item.type === 'external' ? '_blank' : undefined}
|
|
rel={item.type === 'external' ? 'noopener noreferrer' : undefined}
|
|
class="flex items-center justify-between p-4 text-base font-medium text-muted hover:text-foreground hover:bg-surface/50 rounded-xl transition-all group"
|
|
>
|
|
<span class="flex items-center gap-2">
|
|
{t(item.label)}
|
|
{item.type === 'external' && (
|
|
<svg class="h-4 w-4 opacity-60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
|
</svg>
|
|
)}
|
|
</span>
|
|
<svg class="h-4 w-4 opacity-40 group-hover:opacity-60 transition-all" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
</svg>
|
|
</a>
|
|
))}
|
|
|
|
<!-- Mobile CTA -->
|
|
<div class="pt-4 mt-4 border-t border-border/50">
|
|
<a
|
|
href={localizePath("/contact", lang)}
|
|
class="btn btn-primary w-full justify-center"
|
|
>
|
|
Get Started Today
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Progress bar for scroll -->
|
|
<div class="absolute bottom-0 left-0 h-0.5 bg-gradient-to-r from-primary to-accent transition-all duration-300" id="scroll-progress"></div>
|
|
</header>
|
|
|
|
<script>
|
|
// Enhanced mobile menu functionality with animations
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const header = document.getElementById('main-header');
|
|
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
|
const mobileMenu = document.getElementById('mobile-menu');
|
|
const menuIcon = document.getElementById('mobile-menu-icon');
|
|
const closeIcon = document.getElementById('mobile-close-icon');
|
|
const scrollProgress = document.getElementById('scroll-progress');
|
|
|
|
// Header scroll effect
|
|
let lastScrollY = window.scrollY;
|
|
|
|
function updateHeader() {
|
|
const currentScrollY = window.scrollY;
|
|
|
|
if (currentScrollY > 100) {
|
|
header?.classList.add('backdrop-blur-xl', 'bg-background/80');
|
|
header?.classList.remove('bg-transparent');
|
|
} else {
|
|
header?.classList.remove('backdrop-blur-xl', 'bg-background/80');
|
|
header?.classList.add('bg-transparent');
|
|
}
|
|
|
|
// Hide/show header on scroll
|
|
if (currentScrollY > lastScrollY && currentScrollY > 100) {
|
|
header?.classList.add('-translate-y-full');
|
|
} else {
|
|
header?.classList.remove('-translate-y-full');
|
|
}
|
|
|
|
lastScrollY = currentScrollY;
|
|
|
|
// Update progress bar
|
|
const scrollPercentage = (currentScrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100;
|
|
if (scrollProgress) {
|
|
scrollProgress.style.width = `${Math.min(scrollPercentage, 100)}%`;
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', updateHeader, { passive: true });
|
|
|
|
// Mobile menu toggle with enhanced animations
|
|
if (mobileMenuButton && mobileMenu && menuIcon && closeIcon) {
|
|
mobileMenuButton.addEventListener('click', () => {
|
|
const isExpanded = mobileMenuButton.getAttribute('aria-expanded') === 'true';
|
|
const newState = !isExpanded;
|
|
|
|
mobileMenuButton.setAttribute('aria-expanded', newState.toString());
|
|
|
|
if (newState) {
|
|
mobileMenu.classList.remove('hidden');
|
|
// Animate in
|
|
requestAnimationFrame(() => {
|
|
mobileMenu.style.opacity = '0';
|
|
mobileMenu.style.transform = 'translateY(-10px)';
|
|
mobileMenu.style.transition = 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)';
|
|
|
|
requestAnimationFrame(() => {
|
|
mobileMenu.style.opacity = '1';
|
|
mobileMenu.style.transform = 'translateY(0)';
|
|
});
|
|
});
|
|
|
|
menuIcon.classList.add('hidden');
|
|
closeIcon.classList.remove('hidden');
|
|
document.body.style.overflow = 'hidden';
|
|
} else {
|
|
// Animate out
|
|
mobileMenu.style.opacity = '0';
|
|
mobileMenu.style.transform = 'translateY(-10px)';
|
|
|
|
setTimeout(() => {
|
|
mobileMenu.classList.add('hidden');
|
|
document.body.style.overflow = '';
|
|
}, 300);
|
|
|
|
menuIcon.classList.remove('hidden');
|
|
closeIcon.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
// Close menu when clicking outside
|
|
document.addEventListener('click', (event) => {
|
|
if (!mobileMenuButton.contains(event.target as Node) &&
|
|
!mobileMenu.contains(event.target as Node) &&
|
|
!mobileMenu.classList.contains('hidden')) {
|
|
mobileMenuButton.click();
|
|
}
|
|
});
|
|
|
|
// Close menu on escape key
|
|
document.addEventListener('keydown', (event) => {
|
|
if (event.key === 'Escape' && !mobileMenu.classList.contains('hidden')) {
|
|
mobileMenuButton.click();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
/* Enhanced mobile menu animations */
|
|
#mobile-menu {
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
}
|
|
|
|
/* Smooth header transitions */
|
|
#main-header {
|
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
backdrop-filter 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
/* Logo hover effect */
|
|
.group:hover .brightness-0 {
|
|
filter: brightness(1) invert(0);
|
|
transition: filter 0.3s ease;
|
|
}
|
|
</style> |