# All files / src/scroll useScrollLock.ts

90.38% Statements 47/52
81.81% Branches 9/11
100% Functions 1/1
90.38% Lines 47/52

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    531x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    687x
    122x
    98x
    98x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    24x
    122x

    24x
    24x
    24x
    24x
    24x
    24x
    24x

    24x
    687x
    687x
     "use client";
    import { useEffect } from "react";
    import { getScrollbarWidth } from "./getScrollbarWidth.js";

    export const SCROLLBAR_SIZE_VAR = "--rmd-scrollbar-size";

    // this is really just so that nested dialogs will work correctly. Only the
    // first created dialog should prevent scroll locking on the `document.body`
    let isLocked = false;

    /**
     *
     * @internal
     * @remarks
     * \@since 6.0.0 No longer support scroll locking elements other than
     * the `document.body` since it's more reliable to scroll lock with an overlay.
     * \@since 6.0.0 Now applies `paddingRight` equal to the current OS's
     * scrollbar width if there is a full page scrollbar to prevent layout shifting.
     *
     * @param locked - The `document.body` will not be scrollable when this is
     * `true`.
     */
    export function useScrollLock(locked: boolean): void {
      useEffect(() => {
        if (isLocked || !locked) {
          return;
        }

        isLocked = true;

        const size = `${getScrollbarWidth()}px`;
        const el = document.body;
        const { paddingRight } = el.style;
        const isScrollbarVisible = el.scrollHeight > el.offsetHeight;

        el.style.overflow = "hidden";
        if (isScrollbarVisible) {
          el.style.setProperty(SCROLLBAR_SIZE_VAR, size);
          el.style.paddingRight = `var(${SCROLLBAR_SIZE_VAR})`;
        }

        return () => {
          isLocked = false;

          el.style.removeProperty(SCROLLBAR_SIZE_VAR);
          el.style.overflow = "";
          if (isScrollbarVisible) {
            el.style.paddingRight = paddingRight;
          }
        };
      }, [locked]);
    }