From 24fc447888ff3f8b2977af709811b70f965db0a4 Mon Sep 17 00:00:00 2001 From: myothuko98 Date: Sun, 22 Mar 2026 18:30:26 +0700 Subject: [PATCH] :bug: fix(navbar): fix layout shift on language toggle Navbar menu item widths and sign-in button width were changing size when switching between English and Myanmar languages, causing layout instability. - Add `desktopNavWidthByKey` fixed-width map to lock each nav item to a stable Tailwind width class regardless of translated label length - Apply `inline-flex justify-center whitespace-nowrap` on nav links to prevent text-driven width changes - Add `min-w` and `whitespace-nowrap` to `SignInButton` for stable width across locales - Fix React purity issue: replace `Math.random()` in render with static `sparkleDriftX` constant array - Refine desktop nav spacing, gap, and font size for visual balance --- src/components/Auth/SignInButton.tsx | 2 +- src/components/Common/Navbar/Navbar.tsx | 27 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/components/Auth/SignInButton.tsx b/src/components/Auth/SignInButton.tsx index 74db578..7c8e024 100644 --- a/src/components/Auth/SignInButton.tsx +++ b/src/components/Auth/SignInButton.tsx @@ -18,7 +18,7 @@ export default function SignInButton({ className }: { className?: string }) { type="button" onClick={signInWithGoogle} className={cn( - "group relative flex items-center gap-2 px-4 py-2 rounded-full text-sm font-bold uppercase tracking-wider overflow-hidden", + "group relative inline-flex min-w-[7.5rem] items-center justify-center gap-1.5 whitespace-nowrap px-3.5 py-1.75 rounded-full text-sm font-bold uppercase tracking-wider overflow-hidden", "text-zinc-300 hover:text-white transition-all duration-300", className )} diff --git a/src/components/Common/Navbar/Navbar.tsx b/src/components/Common/Navbar/Navbar.tsx index 6de5197..23e4691 100644 --- a/src/components/Common/Navbar/Navbar.tsx +++ b/src/components/Common/Navbar/Navbar.tsx @@ -23,6 +23,17 @@ const linkKeys = [ { key: "jobs", href: "/jobs" }, ] as const; +const desktopNavWidthByKey: Record<(typeof linkKeys)[number]["key"], string> = { + home: "w-[7rem]", + profiles: "w-[6rem]", + editor: "w-[5.5rem]", + howTo: "w-[5.25rem]", + blog: "w-[4.5rem]", + jobs: "w-[5rem]", +}; + +const sparkleDriftX = [-10, 8, 14] as const; + /* ── Prismatic shimmer line along the navbar bottom ── */ const PrismBorder = () => (
@@ -39,7 +50,7 @@ const PrismBorder = () => ( ); /* ── Floating sparkle particles near active indicator ── */ -const Sparkle = ({ delay }: { delay: number }) => ( +const Sparkle = ({ delay, driftX }: { delay: number; driftX: number }) => ( ( animate={{ opacity: [0, 1, 0], y: [0, -18, -28], - x: [0, (Math.random() - 0.5) * 20], + x: [0, driftX], scale: [0, 1.2, 0], }} transition={{ @@ -92,7 +103,7 @@ const ActiveIndicator = () => ( {/* Sparkle particles */}
{[0, 0.6, 1.2].map((d, i) => ( - + ))}
@@ -104,12 +115,14 @@ const NavLink = ({ label, isActive, index, + widthClass, mmFont = "", }: { href: string; label: string; isActive: boolean; index: number; + widthClass: string; mmFont?: string; }) => { const ref = useRef(null); @@ -162,10 +175,11 @@ const NavLink = ({ @@ -350,7 +364,7 @@ const Navbar = () => { {/* Desktop Navigation */}
{/* Primary nav links */} -
+
{linkKeys.map((link, i) => ( { label={t(link.key)} isActive={path === link.href} index={i} + widthClass={desktopNavWidthByKey[link.key]} mmFont={mmFont} /> ))}
{/* Prismatic divider */} -
+
{/* Utility group */}