astro_avtourist/frontend/src/components/layout/header/Header.astro
2026-04-05 18:12:49 +05:00

335 lines
8.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
import Logo from "./Logo.astro";
import Navbar from "./Navbar.astro";
import MobileMenu from "./MobileMenu.astro";
import { COMPANY } from "@constants";
---
<header class="header-wrapper" id="header">
<!-- 1. Контейнер шапки -->
<div class="site-container header-container">
<div class="header-column header-left animate-load" data-delay="0">
<Logo />
</div>
<!--Navbar -->
<div
class="header-column header-center desktop-nav animate-load"
data-delay="100"
>
<Navbar />
</div>
<!-- Phone -->
<div class="header-column header-right animate-load" data-delay="200">
<div class="header-actions">
<a href={`tel:${COMPANY.phone}`} class="header-phone">
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="phone-icon"
>
<path
d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
></path>
</svg>
<span class="phone-number">{COMPANY.phone}</span>
</a>
</div>
<button class="burger-btn" id="burger-btn" aria-label="Открыть меню">
<span class="burger-line"></span>
<span class="burger-line"></span>
<span class="burger-line"></span>
</button>
</div>
</div>
<!-- 2. Линия прогресса (теперь под контейнером, с высоким z-index) -->
<div class="header-progress-container animate-load" data-delay="300">
<div class="header-progress-bar" id="progress-bar"></div>
</div>
</header>
<MobileMenu />
<style>
.header-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: var(--color-light);
z-index: 1000;
transition:
background-color 0.3s ease,
box-shadow 0.3s ease;
margin: 0 !important;
padding: 0 !important;
border-bottom: 1px solid rgba(30, 48, 80, 0.05);
}
.header-wrapper.scrolled {
background-color: rgba(209, 217, 228, 0.98);
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.header-container {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
height: 80px;
transition: height 0.3s ease;
}
.header-wrapper.scrolled .header-container {
height: 70px;
}
.header-column {
display: flex;
align-items: center;
}
.header-left {
justify-content: flex-start;
}
.header-center {
justify-content: center;
}
.header-right {
justify-content: flex-end;
gap: 1.5rem;
}
/* НОМЕР ТЕЛЕФОНА В ШАПКЕ */
.header-phone {
display: flex;
align-items: center;
gap: 0.5rem;
color: #1e3050;
text-decoration: none;
font-weight: 600;
font-size: 0.95rem;
white-space: nowrap;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
padding: 0.6rem 1.2rem;
border-radius: 10px;
overflow: hidden;
letter-spacing: 0.3px;
cursor: pointer;
background: transparent;
position: relative;
}
.header-phone:hover {
color: #0a1a2e;
background: rgba(30, 48, 80, 0.05);
transform: translateY(-2px);
}
/* Эффект перелива при наведении */
.header-phone::after {
content: "";
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(234, 194, 110, 0.1),
transparent
);
transition: left 0.5s ease;
pointer-events: none;
}
.header-phone:hover::after {
left: 100%;
}
.phone-icon {
flex-shrink: 0;
transition: transform 0.3s ease;
}
.header-phone:hover .phone-icon {
transform: scale(1.1);
}
.phone-number {
font-weight: 700;
}
/* ПОЛОСА ПРОГРЕССА */
.header-progress-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
background: rgba(234, 194, 110, 0.1);
z-index: 1001; /* Выше фона шапки */
overflow: hidden;
}
.header-progress-bar {
height: 100%;
width: 0%;
background: linear-gradient(90deg, #eac26e 0%, #f0d68a 50%, #eac26e 100%);
box-shadow: 0 0 10px rgba(234, 194, 110, 0.5);
}
/* БУРГЕР */
.burger-btn {
display: none;
flex-direction: column;
justify-content: space-between;
width: 28px;
height: 18px;
background: transparent;
border: none;
cursor: pointer;
transition: opacity 0.3s ease;
}
.burger-line {
width: 100%;
height: 2.5px;
background-color: #1e3050;
border-radius: 4px;
}
/* Скрытие гамбургера при открытом меню */
.burger-btn.active {
opacity: 0;
pointer-events: none;
}
/* --- АНИМАЦИИ ПРИ ЗАГРУЗКЕ --- */
.animate-load {
opacity: 0;
transform: translateY(-20px);
transition:
opacity 0.6s cubic-bezier(0.4, 0, 0.2, 1),
transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
will-change: opacity, transform;
}
.animate-load.is-visible {
opacity: 1;
transform: translateY(0);
}
/* Задержки для последовательного появления */
.header-left[data-delay="0"] {
transition-delay: 0s;
}
.header-center[data-delay="100"] {
transition-delay: 0.1s;
}
.header-right[data-delay="200"] {
transition-delay: 0.2s;
}
.header-progress-container[data-delay="300"] {
transition-delay: 0.3s;
}
/* Уважаем prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.animate-load {
opacity: 1;
transform: none;
transition: none;
}
}
@media (max-width: 992px) {
.header-container {
display: flex;
justify-content: space-between;
height: 70px;
}
.header-center {
display: none;
}
.header-right {
gap: 0.75rem;
}
.header-phone {
display: none;
}
.burger-btn {
display: flex;
}
}
@media (min-width: 993px) {
.header-phone {
display: flex;
}
}
@media (max-width: 767px) {
.header-container {
height: 64px;
padding: 0 1rem;
}
}
</style>
<script>
// Анимация при загрузке страницы
document.addEventListener("DOMContentLoaded", () => {
const animatedElements = document.querySelectorAll(".animate-load");
animatedElements.forEach((el) => {
const delay = parseInt((el as HTMLElement).dataset.delay || "0");
setTimeout(() => {
el.classList.add("is-visible");
}, delay);
});
});
document.addEventListener("DOMContentLoaded", () => {
const burgerBtn = document.getElementById("burger-btn");
const mobileMenuOverlay = document.getElementById("mobile-menu-overlay");
const progressBar = document.getElementById("progress-bar");
const header = document.getElementById("header");
function updateScroll() {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const docHeight =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
if (progressBar && docHeight > 0) {
const scrollPercent = (scrollTop / docHeight) * 100;
progressBar.style.width = `${Math.min(100, Math.max(0, scrollPercent))}%`;
}
if (scrollTop > 10) header?.classList.add("scrolled");
else header?.classList.remove("scrolled");
}
window.addEventListener("scroll", updateScroll, { passive: true });
// Открытие меню - добавляем active к бургеру для скрытия
burgerBtn?.addEventListener("click", () => {
mobileMenuOverlay?.classList.add("active");
burgerBtn?.classList.add("active");
document.body.style.overflow = "hidden";
});
updateScroll();
});
</script>