(isActive: boolean)
| 5 | * Uses position: fixed + scroll restoration (avoids layout shift). |
| 6 | */ |
| 7 | export function useScrollLock(isActive: boolean) { |
| 8 | const scrollYRef = useRef(0) |
| 9 | |
| 10 | useEffect(() => { |
| 11 | if (!isActive) return |
| 12 | |
| 13 | scrollYRef.current = window.scrollY |
| 14 | const body = document.body |
| 15 | const html = document.documentElement |
| 16 | |
| 17 | const prevBodyStyle = { |
| 18 | position: body.style.position, |
| 19 | top: body.style.top, |
| 20 | width: body.style.width, |
| 21 | } |
| 22 | const prevHtmlOverscroll = html.style.overscrollBehavior |
| 23 | |
| 24 | body.style.position = "fixed" |
| 25 | body.style.top = `-${scrollYRef.current}px` |
| 26 | body.style.width = "100%" |
| 27 | |
| 28 | html.style.overscrollBehavior = "contain" |
| 29 | |
| 30 | return () => { |
| 31 | body.style.position = prevBodyStyle.position |
| 32 | body.style.top = prevBodyStyle.top |
| 33 | body.style.width = prevBodyStyle.width |
| 34 | html.style.overscrollBehavior = prevHtmlOverscroll |
| 35 | |
| 36 | window.scrollTo(0, scrollYRef.current) |
| 37 | } |
| 38 | }, [isActive]) |
| 39 | } |
no outgoing calls
no test coverage detected
searching dependent graphs…