Skip to main content
Prevents document.body from scrolling while locked is true. Compensates for the scrollbar width so the layout doesn’t shift.

Usage

import { useScrollLock } from '@kivora/react';

function Modal({ isOpen, onClose }) {
  useScrollLock(isOpen);

  if (!isOpen) return null;

  return (
    <div className="modal-overlay">
      <div className="modal">
        <button onClick={onClose}>Close</button>
        {/* Modal content */}
      </div>
    </div>
  );
}

Parameters

locked
boolean
required
When true, prevents scrolling on the document body.

Examples

function ModalDialog({ open, children }) {
  useScrollLock(open);

  return open ? (
    <div className="fixed inset-0 overflow-y-auto">
      <div className="modal-content">{children}</div>
    </div>
  ) : null;
}

Conditional lock with state

function App() {
  const [menuOpen, setMenuOpen] = useState(false);
  
  useScrollLock(menuOpen);

  return (
    <>
      <button onClick={() => setMenuOpen(true)}>Open Menu</button>
      {menuOpen && (
        <nav className="sidebar">
          <button onClick={() => setMenuOpen(false)}>Close</button>
          {/* Navigation items */}
        </nav>
      )}
    </>
  );
}

Multiple overlays

function App() {
  const [modalOpen, setModalOpen] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  
  // Lock scroll when either is open
  useScrollLock(modalOpen || drawerOpen);

  return (
    <>
      <button onClick={() => setModalOpen(true)}>Open Modal</button>
      <button onClick={() => setDrawerOpen(true)}>Open Drawer</button>
      {/* Modal and drawer components */}
    </>
  );
}

Notes

  • Automatically compensates for scrollbar width to prevent layout shift
  • Restores original overflow and paddingRight styles on unlock
  • Safe to use with multiple instances—cleanup happens automatically

Type Definitions

function useScrollLock(locked: boolean): void;

Build docs developers (and LLMs) love