/* eslint-disable react-hooks/exhaustive-deps */ import React, { useEffect, useRef, useState } from 'react'; interface CapsuleSwitchProps { options: { label: string; value: string }[]; active: string; onChange: (value: string) => void; className?: string; } const CapsuleSwitch: React.FC = ({ options, active, onChange, className, }) => { const containerRef = useRef(null); const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]); const [indicatorStyle, setIndicatorStyle] = useState<{ left: number; width: number; }>({ left: 0, width: 0 }); const activeIndex = options.findIndex((opt) => opt.value === active); // 更新指示器位置 const updateIndicatorPosition = () => { if ( activeIndex >= 0 && buttonRefs.current[activeIndex] && containerRef.current ) { const button = buttonRefs.current[activeIndex]; const container = containerRef.current; if (button && container) { const buttonRect = button.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); if (buttonRect.width > 0) { setIndicatorStyle({ left: buttonRect.left - containerRect.left, width: buttonRect.width, }); } } } }; // 组件挂载时立即计算初始位置 useEffect(() => { const timeoutId = setTimeout(updateIndicatorPosition, 0); return () => clearTimeout(timeoutId); }, []); // 监听选中项变化 useEffect(() => { const timeoutId = setTimeout(updateIndicatorPosition, 0); return () => clearTimeout(timeoutId); }, [activeIndex]); return (
{/* 滑动的白色背景指示器 */} {indicatorStyle.width > 0 && (
)} {options.map((opt, index) => { const isActive = active === opt.value; return ( ); })}
); }; export default CapsuleSwitch;