qlik-oss/sn-table

View on GitHub
src/table/virtualized-table/hooks/use-scrollbar-width.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import { useLayoutEffect, useState } from "react";
import { TableContext, useContextSelector } from "../../context";

const useScrollbarWidth = (ref: React.RefObject<HTMLDivElement>) => {
  const { layout, rect, theme } = useContextSelector(TableContext, (value) => value.baseProps);
  const themeName = theme.name();
  const [xScrollbarWidth, setXScrollbarWidth] = useState(0);
  const [yScrollbarWidth, setYScrollbarWidth] = useState(0);

  /**
   * Scenarios that could change the container size OR the width column/s
   * has the potential to make a scrollbar appear.
   * - Theme change (Ex: font size)
   * - Layout change (Ex: column width property or fields added/removed)
   * - Container element is re-sized
   *
   * A column that is actively re-sized by the user can also cause a
   * scrollbar to appear. But that would trigger a state update while
   * the user is re-sizing, which causes a column size to "jump" in
   * a some what unpredictable maner. So we simply ignore that and
   * let the layout update when the user is done, catch the new column size.
   */
  useLayoutEffect(() => {
    if (ref.current) {
      const { offsetWidth = 0, offsetHeight = 0, clientWidth = 0, clientHeight = 0 } = ref.current ?? {};
      const widthDiff = offsetWidth - clientWidth;
      const heightDiff = offsetHeight - clientHeight;
      setYScrollbarWidth(widthDiff);
      setXScrollbarWidth(heightDiff);
    }
  }, [ref, layout, rect, themeName]);

  return { xScrollbarWidth, yScrollbarWidth };
};

export default useScrollbarWidth;