@@ -276,6 +276,39 @@ export default function GraphFunctionalPage() {
276276 const svgRef = useRef < SVGSVGElement > ( null ) ;
277277 const depthRef = useRef < Map < string , number > > ( new Map ( ) ) ;
278278
279+ // Prevent vertical scroll on mobile while dragging the graph
280+ useEffect ( ( ) => {
281+ const container = containerRef . current ;
282+ if ( ! container ) return ;
283+ let active = false ;
284+ let lastX = 0 , lastY = 0 ;
285+ const onTouchStart = ( e : TouchEvent ) => {
286+ if ( e . touches . length === 1 ) {
287+ lastX = e . touches [ 0 ] . clientX ;
288+ lastY = e . touches [ 0 ] . clientY ;
289+ active = true ;
290+ }
291+ } ;
292+ const onTouchMove = ( e : TouchEvent ) => {
293+ if ( ! active ) return ;
294+ const dx = Math . abs ( e . touches [ 0 ] . clientX - lastX ) ;
295+ const dy = Math . abs ( e . touches [ 0 ] . clientY - lastY ) ;
296+ // Only preventDefault if the user is dragging horizontally or vertically (not just tapping)
297+ if ( dx > 2 || dy > 2 ) {
298+ e . preventDefault ( ) ;
299+ }
300+ } ;
301+ const onTouchEnd = ( ) => { active = false ; } ;
302+ container . addEventListener ( "touchstart" , onTouchStart , { passive : false } ) ;
303+ container . addEventListener ( "touchmove" , onTouchMove , { passive : false } ) ;
304+ container . addEventListener ( "touchend" , onTouchEnd ) ;
305+ return ( ) => {
306+ container . removeEventListener ( "touchstart" , onTouchStart ) ;
307+ container . removeEventListener ( "touchmove" , onTouchMove ) ;
308+ container . removeEventListener ( "touchend" , onTouchEnd ) ;
309+ } ;
310+ } , [ ] ) ;
311+
279312 // Dynamic root id (default ECON 201)
280313 const [ rootId , setRootId ] = useState < string > ( "ECON 201" ) ;
281314
@@ -1164,7 +1197,7 @@ export default function GraphFunctionalPage() {
11641197 </ label >
11651198 </ div >
11661199 { /* Controls */ }
1167- < div data-pan-block className = "absolute top-2 right-2 z-20 w-72 bg-white/90 backdrop-blur rounded-lg border border-gray-200 shadow p-3 text-xs text-gray-800" >
1200+ < div data-pan-block className = "absolute top-2 right-2 z-20 w-72 hidden md:block bg-white/90 backdrop-blur rounded-lg border border-gray-200 shadow p-3 text-xs text-gray-800" >
11681201 < div className = "font-medium text-gray-700 mb-2" > Layout controls</ div >
11691202 < div className = "space-y-2" >
11701203 < label className = "flex items-center justify-between gap-2" >
0 commit comments