Skip to content

Commit 24fc447

Browse files
committed
🐛 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
1 parent 7a1c239 commit 24fc447

2 files changed

Lines changed: 22 additions & 7 deletions

File tree

src/components/Auth/SignInButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function SignInButton({ className }: { className?: string }) {
1818
type="button"
1919
onClick={signInWithGoogle}
2020
className={cn(
21-
"group relative flex items-center gap-2 px-4 py-2 rounded-full text-sm font-bold uppercase tracking-wider overflow-hidden",
21+
"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",
2222
"text-zinc-300 hover:text-white transition-all duration-300",
2323
className
2424
)}

src/components/Common/Navbar/Navbar.tsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ const linkKeys = [
2323
{ key: "jobs", href: "/jobs" },
2424
] as const;
2525

26+
const desktopNavWidthByKey: Record<(typeof linkKeys)[number]["key"], string> = {
27+
home: "w-[7rem]",
28+
profiles: "w-[6rem]",
29+
editor: "w-[5.5rem]",
30+
howTo: "w-[5.25rem]",
31+
blog: "w-[4.5rem]",
32+
jobs: "w-[5rem]",
33+
};
34+
35+
const sparkleDriftX = [-10, 8, 14] as const;
36+
2637
/* ── Prismatic shimmer line along the navbar bottom ── */
2738
const PrismBorder = () => (
2839
<div className="absolute bottom-0 left-0 right-0 h-[1px] overflow-hidden">
@@ -39,7 +50,7 @@ const PrismBorder = () => (
3950
);
4051

4152
/* ── Floating sparkle particles near active indicator ── */
42-
const Sparkle = ({ delay }: { delay: number }) => (
53+
const Sparkle = ({ delay, driftX }: { delay: number; driftX: number }) => (
4354
<motion.div
4455
className="absolute rounded-full"
4556
style={{
@@ -52,7 +63,7 @@ const Sparkle = ({ delay }: { delay: number }) => (
5263
animate={{
5364
opacity: [0, 1, 0],
5465
y: [0, -18, -28],
55-
x: [0, (Math.random() - 0.5) * 20],
66+
x: [0, driftX],
5667
scale: [0, 1.2, 0],
5768
}}
5869
transition={{
@@ -92,7 +103,7 @@ const ActiveIndicator = () => (
92103
{/* Sparkle particles */}
93104
<div className="absolute top-0">
94105
{[0, 0.6, 1.2].map((d, i) => (
95-
<Sparkle key={i} delay={d} />
106+
<Sparkle key={i} delay={d} driftX={sparkleDriftX[i]} />
96107
))}
97108
</div>
98109
</motion.div>
@@ -104,12 +115,14 @@ const NavLink = ({
104115
label,
105116
isActive,
106117
index,
118+
widthClass,
107119
mmFont = "",
108120
}: {
109121
href: string;
110122
label: string;
111123
isActive: boolean;
112124
index: number;
125+
widthClass: string;
113126
mmFont?: string;
114127
}) => {
115128
const ref = useRef<HTMLDivElement>(null);
@@ -162,10 +175,11 @@ const NavLink = ({
162175
<MseLink
163176
href={href}
164177
className={cn(
165-
"relative font-display text-[13px] font-bold uppercase tracking-[0.15em] py-2 px-1 transition-colors duration-300",
178+
"relative inline-flex items-center justify-center whitespace-nowrap font-display text-[14px] font-bold uppercase tracking-[0.12em] py-2 px-1 transition-colors duration-300",
166179
isActive
167180
? "text-white"
168181
: "text-zinc-500 hover:text-zinc-200",
182+
widthClass,
169183
mmFont
170184
)}
171185
>
@@ -350,21 +364,22 @@ const Navbar = () => {
350364
{/* Desktop Navigation */}
351365
<div className="hidden lg:flex flex-row items-center">
352366
{/* Primary nav links */}
353-
<div className="flex items-center gap-5 xl:gap-8">
367+
<div className="flex items-center gap-2 xl:gap-2.5">
354368
{linkKeys.map((link, i) => (
355369
<NavLink
356370
key={link.key}
357371
href={link.href}
358372
label={t(link.key)}
359373
isActive={path === link.href}
360374
index={i}
375+
widthClass={desktopNavWidthByKey[link.key]}
361376
mmFont={mmFont}
362377
/>
363378
))}
364379
</div>
365380

366381
{/* Prismatic divider */}
367-
<div className="mx-4 xl:mx-5 h-4 w-px bg-gradient-to-b from-transparent via-white/[0.08] to-transparent" />
382+
<div className="mx-2 xl:mx-2.5 h-4 w-px bg-gradient-to-b from-transparent via-white/[0.08] to-transparent" />
368383

369384
{/* Utility group */}
370385
<div className="flex items-center gap-3">

0 commit comments

Comments
 (0)