Remove header block entrance motion

This commit is contained in:
MOH
2026-03-10 17:42:02 +01:00
parent 8bf2121ffa
commit eceb0f3a54
+49 -39
View File
@@ -5,7 +5,8 @@ import { LayoutDashboard, Menu, X } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useLocale, useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { Container } from "@/components/layout/container";
import { LocaleToggle } from "@/components/layout/locale-toggle";
@@ -106,6 +107,7 @@ export function SiteHeader({
const [isOpen, setIsOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const [logoReplayKey, setLogoReplayKey] = useState(0);
const logoClickTimesRef = useRef<number[]>([]);
const pathname = usePathname();
const locale = useLocale();
const t = useTranslations("navigation");
@@ -114,26 +116,6 @@ export function SiteHeader({
const languageDirection = isArabic ? "rtl" : "ltr";
const titleMotion = getDirectionalReveal(languageDirection);
const subtitleMotion = getDirectionalReveal(languageDirection);
const navEntranceInitial = reducedMotion ? false : { opacity: 0, y: -14, scale: 0.985, filter: "blur(8px)" };
const navEntranceVisible = { opacity: 1, y: 0, scale: 1, filter: "blur(0px)" };
const controlEntranceInitial = reducedMotion
? false
: {
opacity: 0,
x: languageDirection === "rtl" ? -18 : 18,
scale: 0.98,
filter: "blur(8px)",
};
const controlEntranceVisible = { opacity: 1, x: 0, scale: 1, filter: "blur(0px)" };
const mobileMenuInitial = reducedMotion
? false
: {
opacity: 0,
x: languageDirection === "rtl" ? -14 : 14,
scale: 0.94,
filter: "blur(8px)",
};
const mobileMenuVisible = { opacity: 1, x: 0, scale: 1, filter: "blur(0px)" };
const brandSubtitle = isArabic
? "مــــــطـــــــــــــور ويــــــــــب | فــــــــــــريــــــلانــــــســــــر"
: "Webdesigner Bremen | Freelancer";
@@ -157,6 +139,24 @@ export function SiteHeader({
};
}, []);
const handleLogoClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
setLogoReplayKey((value) => value + 1);
const now = Date.now();
const recentClicks = logoClickTimesRef.current.filter((time) => now - time < 1200);
const nextClicks = [...recentClicks, now];
logoClickTimesRef.current = nextClicks;
if (nextClicks.length < 3) {
return;
}
logoClickTimesRef.current = [];
event.preventDefault();
toast(t("logoTripleClick"));
};
return (
<header className="fixed inset-x-0 top-3 z-40 bg-transparent">
<Container className="max-w-[88rem] px-5 sm:px-6 lg:px-8">
@@ -173,7 +173,7 @@ export function SiteHeader({
<Link
href={getLocalizedPath(locale)}
className="inline-flex items-center gap-2.5 rounded-pill px-1 py-1 sm:gap-3 lg:py-2"
onClick={() => setLogoReplayKey((value) => value + 1)}
onClick={handleLogoClick}
>
<SiteLogo
lightLogoUrl={lightLogoUrl}
@@ -230,13 +230,9 @@ export function SiteHeader({
<div className="col-start-2 hidden justify-center lg:flex">
<motion.nav
initial={navEntranceInitial}
animate={
isScrolled
? { opacity: 1, y: -1, scale: 0.985, filter: "blur(0px)" }
: navEntranceVisible
}
transition={reducedMotion ? { duration: 0 } : { duration: 0.56, delay: 0.22, ease: [0.22, 1, 0.36, 1] }}
initial={false}
animate={isScrolled ? { y: -1, scale: 0.985 } : { y: 0, scale: 1 }}
transition={reducedMotion ? { duration: 0 } : { duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
className={cn(
"inline-flex items-center gap-1 rounded-pill border border-border/70 bg-background/80 p-1.5 backdrop-blur-chrome",
isArabic ? "w-auto max-w-none" : "min-w-[27rem] max-w-[42rem]",
@@ -247,13 +243,9 @@ export function SiteHeader({
</div>
<motion.div
initial={controlEntranceInitial}
animate={
isScrolled
? { opacity: 0, x: languageDirection === "rtl" ? -28 : 28, scale: 0.98, filter: "blur(4px)" }
: controlEntranceVisible
}
transition={reducedMotion ? { duration: 0 } : { duration: 0.56, delay: 0.3, ease: [0.22, 1, 0.36, 1] }}
initial={false}
animate={isScrolled ? { opacity: 0, x: 28 } : { opacity: 1, x: 0 }}
transition={reducedMotion ? { duration: 0 } : { duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
className={cn(
"col-start-3 hidden items-center justify-end lg:flex",
isScrolled ? "pointer-events-none invisible" : "",
@@ -262,16 +254,25 @@ export function SiteHeader({
<div className={desktopControlRailClassName}>
<LocaleToggle
locale={locale}
localeChangedLabels={{
de: t("localeChangedDe"),
en: t("localeChangedEn"),
ar: t("localeChangedAr"),
}}
className={desktopControlButtonClassName}
/>
<SoundToggle
ariaLabel={t("soundMute")}
mutedAriaLabel={t("soundUnmute")}
mutedToastLabel={t("soundMuted")}
unmutedToastLabel={t("soundEnabled")}
variant="ghost"
className={desktopControlButtonClassName}
/>
<ThemeToggle
ariaLabel={t("themeToggle")}
lightToastLabel={t("themeLight")}
darkToastLabel={t("themeDark")}
variant="ghost"
className={desktopControlButtonClassName}
/>
@@ -286,9 +287,9 @@ export function SiteHeader({
</motion.div>
<motion.div
initial={mobileMenuInitial}
animate={mobileMenuVisible}
transition={reducedMotion ? { duration: 0 } : { duration: 0.52, delay: 0.2, ease: [0.22, 1, 0.36, 1] }}
initial={false}
animate={{ opacity: 1, x: 0, scale: 1, filter: "blur(0px)" }}
transition={reducedMotion ? { duration: 0 } : { duration: 0.2, ease: [0.22, 1, 0.36, 1] }}
className="col-start-3 ml-auto justify-self-end lg:hidden"
>
<Button
@@ -391,17 +392,26 @@ export function SiteHeader({
<div className="flex items-center justify-between gap-2">
<LocaleToggle
locale={locale}
localeChangedLabels={{
de: t("localeChangedDe"),
en: t("localeChangedEn"),
ar: t("localeChangedAr"),
}}
className={mobileControlButtonClassName}
/>
<div className="flex items-center gap-2">
<SoundToggle
ariaLabel={t("soundMute")}
mutedAriaLabel={t("soundUnmute")}
mutedToastLabel={t("soundMuted")}
unmutedToastLabel={t("soundEnabled")}
variant="ghost"
className={mobileControlButtonClassName}
/>
<ThemeToggle
ariaLabel={t("themeToggle")}
lightToastLabel={t("themeLight")}
darkToastLabel={t("themeDark")}
variant="ghost"
className={mobileControlButtonClassName}
/>