diff options
| author | Yuval Adam <_@yuv.al> | 2025-09-24 10:36:56 +0200 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2025-09-24 10:36:56 +0200 |
| commit | 4c2c99b7871199210ed1ddc8a4ae0480a25746b5 (patch) | |
| tree | fa4094a88e2aeea9dc711319dddbc9906d20043f /src | |
| parent | 891330d98d75b8621bda2dd7528e099af287060c (diff) | |
Handle mobile touch events in slider
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Slider.tsx | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/src/components/Slider.tsx b/src/components/Slider.tsx index bdca22c..22a8f8f 100644 --- a/src/components/Slider.tsx +++ b/src/components/Slider.tsx @@ -13,41 +13,54 @@ export function Slider({ playback, slider, setSlider }: SliderProps) { const max = playback ? PLAYBACK_SLOTS : 9; - const handleMouseDown = useCallback((e: React.MouseEvent) => { + const handleStart = useCallback((e: React.MouseEvent | React.TouchEvent) => { setIsDragging(true); updateSliderValue(e); }, []); - const updateSliderValue = useCallback((e: MouseEvent | React.MouseEvent) => { + const updateSliderValue = useCallback((e: MouseEvent | React.MouseEvent | TouchEvent | React.TouchEvent) => { if (!sliderRef.current) return; const rect = sliderRef.current.getBoundingClientRect(); - const percentage = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width)); + let clientX: number; + + if ('touches' in e) { + clientX = e.touches?.[0]?.clientX || (e as TouchEvent).changedTouches?.[0]?.clientX || 0; + } else { + clientX = e.clientX; + } + + const percentage = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width)); const value = Math.round(percentage * max); setSlider(value); }, [max, setSlider]); - const handleMouseMove = useCallback((e: MouseEvent) => { + const handleMove = useCallback((e: MouseEvent | TouchEvent) => { if (isDragging) { + e.preventDefault(); updateSliderValue(e); } }, [isDragging, updateSliderValue]); - const handleMouseUp = useCallback(() => { + const handleEnd = useCallback(() => { setIsDragging(false); }, []); React.useEffect(() => { if (isDragging) { - document.addEventListener('mousemove', handleMouseMove); - document.addEventListener('mouseup', handleMouseUp); + document.addEventListener('mousemove', handleMove); + document.addEventListener('mouseup', handleEnd); + document.addEventListener('touchmove', handleMove, { passive: false }); + document.addEventListener('touchend', handleEnd); return () => { - document.removeEventListener('mousemove', handleMouseMove); - document.removeEventListener('mouseup', handleMouseUp); + document.removeEventListener('mousemove', handleMove); + document.removeEventListener('mouseup', handleEnd); + document.removeEventListener('touchmove', handleMove); + document.removeEventListener('touchend', handleEnd); }; } - }, [isDragging, handleMouseMove, handleMouseUp]); + }, [isDragging, handleMove, handleEnd]); const percentage = (slider / max) * 100; @@ -55,8 +68,9 @@ export function Slider({ playback, slider, setSlider }: SliderProps) { <div id="slider" className="py-2.5 fixed bottom-[8vh] w-[30vw] ml-[35vw] max-[812px]:w-[80vw] max-[812px]:ml-[8vw] max-[812px]:z-10"> <div ref={sliderRef} - className="relative h-5 bg-blue-500 rounded-full cursor-pointer" - onMouseDown={handleMouseDown} + className="relative h-5 bg-blue-500 rounded-full cursor-pointer touch-none" + onMouseDown={handleStart} + onTouchStart={handleStart} > <div className={`absolute -top-2.5 w-10 h-10 bg-white rounded-full shadow-md z-[1] ${ |
