Skip to content

Commit d0cb301

Browse files
lwinmoepaingclaude
andcommitted
⚡ perf(footer): remove mouse-tracking glow effects for better performance
Strip useMotionValue/useSpring/useTransform cursor-following glow from FooterLink and simplify SocialLink hover to CSS-only transitions. Reduces per-frame JS work in the footer while keeping entrance animations and decorative elements intact. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1a8d70b commit d0cb301

1 file changed

Lines changed: 14 additions & 73 deletions

File tree

src/components/Common/Footer/Footer.tsx

Lines changed: 14 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,8 @@
33
import { cn } from "@/utils";
44
import Container from "../Container/Container";
55
import Link from "next/link";
6-
import {
7-
motion,
8-
useInView,
9-
useMotionValue,
10-
useSpring,
11-
useTransform,
12-
} from "motion/react";
13-
import { useRef, useCallback } from "react";
6+
import { motion, useInView } from "motion/react";
7+
import { useRef } from "react";
148
import { Github, Users, Heart, ArrowUpRight } from "lucide-react";
159
import { useTranslations } from "next-intl";
1610
import { useLanguage } from "@/hooks/useLanguage";
@@ -88,7 +82,7 @@ const GridDecoration = () => (
8882
</div>
8983
);
9084

91-
/* ── Footer nav link with glow hover ── */
85+
/* ── Footer nav link ── */
9286
const FooterLink = ({
9387
href,
9488
children,
@@ -106,24 +100,6 @@ const FooterLink = ({
106100
isInView: boolean;
107101
mmFont?: string;
108102
}) => {
109-
const ref = useRef<HTMLDivElement>(null);
110-
const mouseX = useMotionValue(0);
111-
const mouseY = useMotionValue(0);
112-
const springX = useSpring(mouseX, { stiffness: 300, damping: 30 });
113-
const springY = useSpring(mouseY, { stiffness: 300, damping: 30 });
114-
const glowOpacity = useMotionValue(0);
115-
const springOpacity = useSpring(glowOpacity, { stiffness: 200, damping: 25 });
116-
117-
const handleMouseMove = useCallback(
118-
(e: React.MouseEvent) => {
119-
if (!ref.current) return;
120-
const rect = ref.current.getBoundingClientRect();
121-
mouseX.set(e.clientX - rect.left);
122-
mouseY.set(e.clientY - rect.top);
123-
},
124-
[mouseX, mouseY]
125-
);
126-
127103
const linkProps = external
128104
? { target: "_blank" as const, rel: "noopener noreferrer" }
129105
: {};
@@ -132,7 +108,6 @@ const FooterLink = ({
132108

133109
return (
134110
<motion.div
135-
ref={ref}
136111
className="relative group"
137112
initial={{ opacity: 0, x: -10 }}
138113
animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: -10 }}
@@ -141,39 +116,19 @@ const FooterLink = ({
141116
delay: 0.3 + index * 0.08,
142117
ease: [0.22, 1, 0.36, 1],
143118
}}
144-
onMouseMove={handleMouseMove}
145-
onMouseEnter={() => glowOpacity.set(1)}
146-
onMouseLeave={() => glowOpacity.set(0)}
147119
>
148-
{/* Cursor-following glow */}
149-
<motion.div
150-
className="pointer-events-none absolute -inset-2 rounded-lg"
151-
style={{
152-
x: useTransform(springX, (v) => v - 50),
153-
y: useTransform(springY, (v) => v - 50),
154-
width: 100,
155-
height: 100,
156-
background: `radial-gradient(circle, ${color}18 0%, transparent 70%)`,
157-
opacity: springOpacity,
158-
}}
159-
/>
160-
161120
<Component
162121
href={href}
163122
{...linkProps}
164123
className={cn("relative flex items-center gap-2 text-sm text-zinc-500 transition-colors duration-300 group-hover:text-zinc-200 py-1", mmFont)}
165124
>
166-
<span className="relative z-10">{children}</span>
167-
<motion.span
168-
className="opacity-0 group-hover:opacity-100 transition-opacity duration-300"
169-
initial={{ x: -4 }}
170-
whileHover={{ x: 0 }}
171-
>
125+
<span>{children}</span>
126+
<span className="opacity-0 group-hover:opacity-100 transition-opacity duration-300">
172127
<ArrowUpRight className="w-3 h-3" style={{ color }} />
173-
</motion.span>
128+
</span>
174129

175130
{/* Underline reveal on hover */}
176-
<motion.span
131+
<span
177132
className="absolute -bottom-0 left-0 right-6 h-[1px] origin-left scale-x-0 group-hover:scale-x-100 transition-transform duration-300"
178133
style={{ background: `linear-gradient(90deg, ${color}, transparent)` }}
179134
/>
@@ -213,39 +168,25 @@ const SocialLink = ({
213168
delay: 0.5 + index * 0.12,
214169
ease: [0.22, 1, 0.36, 1],
215170
}}
216-
whileHover={{ x: 4 }}
217171
>
218-
{/* Icon container with glow */}
219-
<motion.div
220-
className="relative flex items-center justify-center w-9 h-9 rounded-xl overflow-hidden"
172+
{/* Icon container */}
173+
<div
174+
className="relative flex items-center justify-center w-9 h-9 rounded-xl overflow-hidden group-hover:brightness-125 transition-all duration-300"
221175
style={{
222176
background: `linear-gradient(135deg, ${color}12, ${color}06)`,
223177
border: `1px solid ${color}20`,
224178
}}
225-
whileHover={{
226-
scale: 1.1,
227-
boxShadow: `0 0 20px ${color}30, 0 0 40px ${color}10`,
228-
}}
229-
transition={{ type: "spring", stiffness: 400, damping: 25 }}
230179
>
231-
<Icon className="w-4 h-4 relative z-10" style={{ color }} />
232-
233-
{/* Shimmer on hover */}
234-
<motion.div
235-
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-500"
236-
style={{
237-
background: `linear-gradient(135deg, ${color}15, transparent)`,
238-
}}
239-
/>
240-
</motion.div>
180+
<Icon className="w-4 h-4" style={{ color }} />
181+
</div>
241182

242183
<span className={cn("text-sm text-zinc-500 group-hover:text-zinc-300 transition-colors duration-300", mmFont)}>
243184
{label}
244185
</span>
245186

246-
<motion.span className="opacity-0 group-hover:opacity-70 transition-opacity duration-300">
187+
<span className="opacity-0 group-hover:opacity-70 transition-opacity duration-300">
247188
<ArrowUpRight className="w-3 h-3" style={{ color }} />
248-
</motion.span>
189+
</span>
249190
</motion.a>
250191
);
251192

0 commit comments

Comments
 (0)