diff --git a/src/components/playground/PhoneSimulator.tsx b/src/components/playground/PhoneSimulator.tsx index cf81601..d4a35fe 100644 --- a/src/components/playground/PhoneSimulator.tsx +++ b/src/components/playground/PhoneSimulator.tsx @@ -84,30 +84,41 @@ export function PhoneSimulator({ const [isDragging, setIsDragging] = useState(false); const dragOffset = useRef({ x: 0, y: 0 }); - const handleDragStart = (e: React.MouseEvent) => { + const handleDragStart = (e: React.MouseEvent | React.TouchEvent) => { + e.preventDefault(); setIsDragging(true); + const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX; + const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY; dragOffset.current = { - x: e.clientX - visualizerPosition.x, - y: e.clientY - visualizerPosition.y, + x: clientX - visualizerPosition.x, + y: clientY - visualizerPosition.y, }; }; - const handleDragMove = (e: MouseEvent) => { + const handleDragMove = (e: MouseEvent | TouchEvent) => { if (!isDragging || !phoneContainerRef.current || !visualizerRef.current) return; + e.preventDefault(); + const containerRect = phoneContainerRef.current.getBoundingClientRect(); const visualizerRect = visualizerRef.current.getBoundingClientRect(); - let newX = e.clientX - dragOffset.current.x; - let newY = e.clientY - dragOffset.current.y; + const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX; + const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY; + + let newX = clientX - dragOffset.current.x; + let newY = clientY - dragOffset.current.y; // Constrain within container const maxX = containerRect.width - visualizerRect.width; const maxY = containerRect.height - visualizerRect.height; - const statusBarHeight = 48; // h-12 = 48px + // On mobile (width < 768px), status bar is hidden, so allow dragging to top (y=0) + // On desktop, keep status bar height constraint (48px) + const isMobile = typeof window !== 'undefined' && window.innerWidth < 768; + const minY = isMobile ? 0 : 48; // statusBarHeight = 48px newX = Math.max(0, Math.min(newX, maxX)); - newY = Math.max(statusBarHeight, Math.min(newY, maxY)); + newY = Math.max(minY, Math.min(newY, maxY)); setVisualizerPosition({ x: newX, @@ -123,10 +134,14 @@ export function PhoneSimulator({ if (isDragging) { window.addEventListener("mouseup", handleDragEnd); window.addEventListener("mousemove", handleDragMove); + window.addEventListener("touchend", handleDragEnd); + window.addEventListener("touchmove", handleDragMove, { passive: false }); } return () => { window.removeEventListener("mouseup", handleDragEnd); window.removeEventListener("mousemove", handleDragMove); + window.removeEventListener("touchend", handleDragEnd); + window.removeEventListener("touchmove", handleDragMove); }; }, [isDragging]); @@ -792,7 +807,7 @@ export function PhoneSimulator({ })(); return ( -