From 4c2c99b7871199210ed1ddc8a4ae0480a25746b5 Mon Sep 17 00:00:00 2001
From: Yuval Adam <_@yuv.al>
Date: Wed, 24 Sep 2025 10:36:56 +0200
Subject: Handle mobile touch events in slider

---
 src/components/Slider.tsx | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

(limited to 'src/components/Slider.tsx')

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] ${
-- 
cgit v1.3.1

