chore: add client/src/components/layout/Header.tsx
This commit is contained in:
parent
b01002e1ef
commit
2e0b5deee6
1 changed files with 67 additions and 0 deletions
67
client/src/components/layout/Header.tsx
Normal file
67
client/src/components/layout/Header.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { Link } from "wouter";
|
||||||
|
import { ShoppingBag, User, Menu, X } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useCart } from "../../hooks/use-cart";
|
||||||
|
import CartDrawer from "./CartDrawer";
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
const { itemCount, toggleCart, isOpen } = useCart();
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
|
const storeName = import.meta.env.VITE_STORE_NAME || "NoShop";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header className="sticky top-0 z-40 bg-background border-b border-border shadow-sm">
|
||||||
|
<div className="max-w-6xl mx-auto px-4 h-16 flex items-center justify-between gap-4">
|
||||||
|
<Link href="/" className="text-xl font-bold tracking-tight text-foreground hover:text-primary transition-colors">
|
||||||
|
{storeName}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<nav className="hidden md:flex items-center gap-6 text-sm font-medium">
|
||||||
|
<Link href="/" className="text-muted-foreground hover:text-foreground transition-colors">Shop</Link>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<Link
|
||||||
|
href="/account"
|
||||||
|
className="text-muted-foreground hover:text-foreground transition-colors p-2"
|
||||||
|
aria-label="Account"
|
||||||
|
data-testid="link-account"
|
||||||
|
>
|
||||||
|
<User size={20} />
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
onClick={toggleCart}
|
||||||
|
className="relative text-muted-foreground hover:text-foreground transition-colors p-2"
|
||||||
|
aria-label="Open cart"
|
||||||
|
data-testid="button-open-cart"
|
||||||
|
>
|
||||||
|
<ShoppingBag size={20} />
|
||||||
|
{itemCount > 0 && (
|
||||||
|
<span className="absolute -top-0.5 -right-0.5 bg-primary text-primary-foreground text-xs rounded-full w-5 h-5 flex items-center justify-center font-bold" data-testid="cart-count">
|
||||||
|
{itemCount}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="md:hidden text-muted-foreground hover:text-foreground p-2"
|
||||||
|
onClick={() => setMenuOpen((v) => !v)}
|
||||||
|
aria-label="Menu"
|
||||||
|
>
|
||||||
|
{menuOpen ? <X size={20} /> : <Menu size={20} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{menuOpen && (
|
||||||
|
<div className="md:hidden border-t border-border bg-background px-4 py-4 flex flex-col gap-3 text-sm font-medium">
|
||||||
|
<Link href="/" onClick={() => setMenuOpen(false)} className="text-foreground">Shop</Link>
|
||||||
|
<Link href="/account" onClick={() => setMenuOpen(false)} className="text-foreground">Account</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<CartDrawer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue