Files
landing-for-digital-product/src/widgets/header.tsx
2026-01-02 10:21:37 +03:00

147 lines
5.2 KiB
TypeScript
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.
"use client";
import { useState, useEffect } from "react";
import { cn } from "@/shared/lib/utils";
import { Button } from "@/shared/ui/button";
import { Sheet, SheetContent, SheetTrigger } from "@/shared/ui/sheet";
import { Menu, X } from "lucide-react";
import Link from "next/link";
import { useTheme } from "next-themes";
import { Moon, Sun } from "lucide-react";
const navigation = [
{ name: "Возможности", href: "#features" },
{ name: "Преимущества", href: "#stats" },
{ name: "Как работает", href: "#how-it-works" },
{ name: "Тарифы", href: "#pricing" },
{ name: "FAQ", href: "#faq" },
];
/**
* Header с навигацией
* Sticky header с backdrop blur, мобильное меню, theme toggle
*/
export function Header() {
const [scrolled, setScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const { theme, setTheme } = useTheme();
useEffect(() => {
const handleScroll = () => {
setScrolled(window.scrollY > 20);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
const scrollToSection = (href: string) => {
const element = document.querySelector(href);
if (element) {
element.scrollIntoView({ behavior: "smooth" });
setMobileMenuOpen(false);
}
};
return (
<header
className={cn(
"sticky top-0 z-50 w-full transition-all duration-300",
scrolled
? "bg-background/80 backdrop-blur-lg border-b border-border shadow-sm"
: "bg-transparent"
)}
>
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16 lg:h-20">
{/* Logo */}
<Link href="/" className="flex items-center">
<span className="text-2xl font-bold text-gradient">TaskFlow</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden lg:flex items-center gap-8">
{navigation.map((item) => (
<button
key={item.name}
onClick={() => scrollToSection(item.href)}
className="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
>
{item.name}
</button>
))}
</nav>
{/* Desktop Actions */}
<div className="hidden lg:flex items-center gap-4">
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
>
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
<Button variant="outline" asChild>
<Link href="#pricing">Войти</Link>
</Button>
<Button asChild>
<Link href="#pricing">Начать бесплатно</Link>
</Button>
</div>
{/* Mobile Menu */}
<div className="flex lg:hidden items-center gap-2">
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
>
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
<Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>
<SheetTrigger asChild>
<Button variant="ghost" size="icon">
{mobileMenuOpen ? (
<X className="h-6 w-6" />
) : (
<Menu className="h-6 w-6" />
)}
</Button>
</SheetTrigger>
<SheetContent side="right" className="w-full sm:w-80">
<nav className="flex flex-col gap-4 mt-8">
{navigation.map((item) => (
<button
key={item.name}
onClick={() => scrollToSection(item.href)}
className="text-lg font-medium text-left py-2 hover:text-[var(--feature-accent)] transition-colors"
>
{item.name}
</button>
))}
<div className="flex flex-col gap-3 mt-4 pt-4 border-t">
<Button variant="outline" asChild className="w-full">
<Link href="#pricing">Войти</Link>
</Button>
<Button asChild className="w-full">
<Link href="#pricing">Начать бесплатно</Link>
</Button>
</div>
</nav>
</SheetContent>
</Sheet>
</div>
</div>
</div>
</header>
);
}