├── .gitignore ├── CHANGELOG.md ├── README.md ├── example ├── README.md ├── app │ ├── Example.tsx │ ├── Modal.tsx │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── next-env.d.ts ├── package-lock.json ├── package.json ├── postcss.config.mjs ├── renoun.json ├── tailwind.config.ts └── tsconfig.json ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .next 3 | .turbo 4 | .vercel 5 | dist 6 | node_modules 7 | out 8 | 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # lock-scrollbars 2 | 3 | # 0.4.1 4 | 5 | - Uses position fixed and scroll restoration to prevent scrolling in Safari 6 | 7 | # 0.4.0 8 | 9 | - Uses `AbortController` to remove events, resulting in less code. 10 | - Prevents selecting text in background except for Safari. 11 | - Moves to stable scrollbar and overflow hidden styles. 12 | 13 | # 0.3.4 14 | 15 | - Fixes being able to drag the scrollbar with the mouse by collapsing the 16 | scrollbar width when the scroll lock is active. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lock-scrollbars 2 | 3 | Lock all scrollbars recursively to prevent scrolling the page. Useful for 4 | modals, popovers, and other UI elements that require user interaction before 5 | continuing. 6 | 7 | ## Features 8 | 9 | - Locks all scrollbars on the page 10 | - Allows a specific scrollable element 11 | - Supports nested scroll locks (e.g. popover within a modal) 12 | 13 | [View Example](https://lock-scrollbars.vercel.app/) 14 | 15 | ## Installation 16 | 17 | ```bash 18 | npm install lock-scrollbars 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```ts 24 | import { lockScrollbars } from 'lock-scrollbars' 25 | 26 | const unlockScrollbars = lockScrollbars() 27 | 28 | // ...open a modal or popover 29 | 30 | unlockScrollbars() 31 | ``` 32 | 33 | ### React Example 34 | 35 | ```tsx 36 | import React, { useRef, useEffect } from 'react' 37 | import { lockScrollbars } from 'lock-scrollbars' 38 | 39 | function Modal({ 40 | open, 41 | children, 42 | }: { 43 | open: boolean 44 | children: React.ReactNode 45 | }) { 46 | const dialogRef = useRef(null) 47 | const unlockScrollbars = useRef | null>( 48 | null 49 | ) 50 | 51 | useEffect(() => { 52 | const dialogNode = dialogRef.current 53 | if (dialogNode) { 54 | if (open) { 55 | dialogNode.showModal() 56 | unlockScrollbars.current = lockScrollbars(dialogNode) 57 | } else { 58 | dialogNode.close() 59 | unlockScrollbars.current?.() 60 | } 61 | } 62 | }, [open]) 63 | 64 | return {children} 65 | } 66 | ``` 67 | 68 | ## Development 69 | 70 | ```bash 71 | cd example 72 | npm install 73 | npm run dev 74 | ``` 75 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | # or 14 | bun dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 | 19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 | 21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 22 | 23 | ## Learn More 24 | 25 | To learn more about Next.js, take a look at the following resources: 26 | 27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 | 30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 31 | 32 | ## Deploy on Vercel 33 | 34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 | 36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 37 | -------------------------------------------------------------------------------- /example/app/Example.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import { useState } from 'react' 3 | import { Modal } from './Modal' 4 | 5 | export function Example() { 6 | const [open, setOpen] = useState(false) 7 | 8 | return ( 9 | <> 10 | 16 | setOpen(false)}> 17 |
18 |
19 |

Modal Title

20 | 26 |
27 |
{ 29 | event.preventDefault() 30 | setOpen(false) 31 | }} 32 | > 33 |
34 | 40 | 46 |
47 |
48 | 54 | 60 |
61 |
62 | 68 |