diff --git a/src/components/sections/team/TeamCarousel.tsx b/src/components/sections/team/TeamCarousel.tsx index 9d37a04..9d2f6bd 100644 --- a/src/components/sections/team/TeamCarousel.tsx +++ b/src/components/sections/team/TeamCarousel.tsx @@ -94,30 +94,22 @@ export function TeamCarousel({ members, activeIndex, onActiveChange }: TeamCarou [] ); - // Deferred index update — avoids calling parent setState during render - // (onLostPointerCapture can fire during React reconciliation) - const pendingIndexRef = useRef(null); - useEffect(() => { - if (pendingIndexRef.current !== null) { - onActiveChange(pendingIndexRef.current); - pendingIndexRef.current = null; - } - }); - const onPointerUp = useCallback(() => { if (!dragStartRef.current) return; const startIdx = dragStartRef.current.startIndex; const currentOffset = dragOffset; const wasDrag = Math.abs(currentOffset) > 10; const steps = wasDrag ? Math.round(currentOffset / CARD_SPACING) : 0; - setDragOffset(0); - if (steps !== 0) { - pendingIndexRef.current = wrapIndex(startIdx - steps, total); - } dragStartRef.current = null; isDraggingRef.current = false; pausedUntilRef.current = Date.now() + PAUSE_MS; - }, [total, dragOffset]); + if (steps !== 0) { + // Update index and reset offset in the same batch so the old card + // never becomes center for a frame (prevents label flash) + onActiveChange(wrapIndex(startIdx - steps, total)); + } + setDragOffset(0); + }, [total, dragOffset, onActiveChange]); // Compute interpolated style for each card const baseIndex = dragStartRef.current ? dragStartRef.current.startIndex : activeIndex; @@ -165,6 +157,8 @@ export function TeamCarousel({ members, activeIndex, onActiveChange }: TeamCarou ? "none" : "all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94)", isCenter: absDiff < 0.5, + /** 1 at center, fades to 0 by absDiff=0.6 */ + centerOpacity: clamp(1 - absDiff / 0.6, 0, 1), }; } @@ -228,10 +222,16 @@ export function TeamCarousel({ members, activeIndex, onActiveChange }: TeamCarou draggable={false} /> - {style.isCenter && ( + {style.centerOpacity > 0 && ( <> -
-
+
+

{m.name}