+
onChange(Math.max(1, quantity - 1))}
disabled={quantity <= 1}
aria-label="Menge verringern"
- className={`${buttonSize} flex items-center justify-center text-ink/70 hover:text-forest disabled:opacity-30 disabled:hover:text-ink/70`}
+ className={buttonClass}
>
- −
+
+
+
-
- {quantity}
+
+
+
+ {quantity}
+
+
onChange(Math.min(max, quantity + 1))}
disabled={quantity >= max}
aria-label="Menge erhöhen"
- className={`${buttonSize} flex items-center justify-center text-ink/70 hover:text-forest disabled:opacity-30 disabled:hover:text-ink/70`}
+ className={buttonClass}
>
- +
+
+
+
);
diff --git a/src/components/site-chrome.tsx b/src/components/site-chrome.tsx
index 79fea39..101b7d4 100644
--- a/src/components/site-chrome.tsx
+++ b/src/components/site-chrome.tsx
@@ -1,6 +1,7 @@
"use client";
import Link from "next/link";
+import { usePathname } from "next/navigation";
import { useState, useEffect, useRef, type RefObject } from "react";
import { AnimatePresence, motion, useAnimationControls } from "motion/react";
import { useCartStore, cartItemCount, cartTotalCents } from "@/store/cart-store";
@@ -14,6 +15,7 @@ import { QuantityStepper } from "@/components/quantity-stepper";
import { LanguageSwitcher } from "@/components/language-switcher";
import { useI18n } from "@/i18n/i18n-provider";
import { CartFlight, onCartLanded } from "@/components/cart-flight";
+import { HexMark } from "@/components/honeycomb";
import type { Dictionary } from "@/i18n/dictionary-type";
const FOCUSABLE_SELECTOR =
@@ -271,9 +273,52 @@ function CartIconButton() {
);
}
+/**
+ * Kopfzeile reagiert aufs Scrollen: ab etwas Abstand zum Seitenanfang
+ * bekommt sie Schatten und staerkeres Glas; beim Weiterlesen nach unten
+ * weicht sie aus, beim kleinsten Hochscrollen ist sie sofort wieder da.
+ * Waehrend Warenkorb oder Menue offen sind, bleibt sie stehen.
+ */
+function useHeaderScrollState(locked: boolean) {
+ const [scrolled, setScrolled] = useState(false);
+ const [hidden, setHidden] = useState(false);
+
+ useEffect(() => {
+ let lastY = window.scrollY;
+ let frame = 0;
+ const onScroll = () => {
+ cancelAnimationFrame(frame);
+ frame = requestAnimationFrame(() => {
+ const y = window.scrollY;
+ setScrolled(y > 12);
+ // Kleine Zitterbewegungen (Trackpad) ignorieren.
+ if (Math.abs(y - lastY) > 6) {
+ setHidden(y > lastY && y > 240);
+ lastY = y;
+ }
+ });
+ };
+ onScroll();
+ window.addEventListener("scroll", onScroll, { passive: true });
+ return () => {
+ cancelAnimationFrame(frame);
+ window.removeEventListener("scroll", onScroll);
+ };
+ }, []);
+
+ return { scrolled, hidden: hidden && !locked };
+}
+
+function isActivePath(pathname: string, href: string): boolean {
+ return href === "/" ? pathname === "/" : pathname === href || pathname.startsWith(`${href}/`);
+}
+
export function Header({ companyName }: { companyName: string }) {
const { t } = useI18n();
+ const pathname = usePathname();
const [mobileOpen, setMobileOpen] = useState(false);
+ const cartOpen = useCartStore((s) => s.isOpen);
+ const { scrolled, hidden } = useHeaderScrollState(mobileOpen || cartOpen);
const menuButtonRef = useRef
(null);
const mobileMenuRef = useRef(null);
@@ -287,7 +332,15 @@ export function Header({ companyName }: { companyName: string }) {
return (
<>
-
+
{/*
Eigener, breiterer Wrapper statt der gemeinsamen (max-w-6xl):
Logo + 7-Punkte-Navigation + CTA-Button + Icons brauchen mehr Raum als die
@@ -298,15 +351,21 @@ export function Header({ companyName }: { companyName: string }) {
- {mainNav.map((item) => (
-
- {t.nav[item.key]}
-
- ))}
+ {mainNav.map((item) => {
+ const active = isActivePath(pathname, item.href);
+ return (
+
+ {t.nav[item.key]}
+
+ );
+ })}
@@ -396,8 +455,12 @@ export function Header({ companyName }: { companyName: string }) {
setMobileOpen(false)}
- className="text-3xl font-serif"
+ aria-current={isActivePath(pathname, item.href) ? "page" : undefined}
+ className={`flex items-center gap-3 text-3xl font-serif ${
+ isActivePath(pathname, item.href) ? "text-honey-light" : ""
+ }`}
>
+ {isActivePath(pathname, item.href) ?
: null}
{t.nav[item.key]}
diff --git a/src/components/site-footer.tsx b/src/components/site-footer.tsx
index 923667c..eea6f51 100644
--- a/src/components/site-footer.tsx
+++ b/src/components/site-footer.tsx
@@ -1,4 +1,5 @@
import Link from "next/link";
+import { HoneycombPattern } from "@/components/honeycomb";
import type { ReactNode } from "react";
import { Container } from "@/components/ui";
import { Logomark } from "@/components/logomark";
@@ -116,8 +117,9 @@ export async function Footer({
};
return (
-
-
+
+
+
@@ -180,7 +182,7 @@ function FooterColumn({
{links.map((link) => (
-
+
{labels[link.key]}