diff --git a/src/components/data/datagrid/datagridthead.tsx b/src/components/data/datagrid/datagridthead.tsx index 9ddc60e..b386edc 100644 --- a/src/components/data/datagrid/datagridthead.tsx +++ b/src/components/data/datagrid/datagridthead.tsx @@ -15,11 +15,6 @@ export const DataGridTHead = < >() => { const ref = useRef(null); - const thead = ref.current; - const table = thead?.parentNode as HTMLTableElement | undefined; - const scrollPane = table?.parentNode as HTMLDivElement | undefined; - const toolbar = scrollPane?.previousSibling as HTMLDivElement | undefined; - const { allowOverflowX, dataGridId, @@ -40,49 +35,53 @@ export const DataGridTHead = < window.removeEventListener("resize", stickyFix); window.removeEventListener("scroll", stickyFix); }; - }, [ref.current, height, renderableFields]); + }, [ref.current, height]); /** * Fixes sticky behaviour due to `overflow-y: auto;` and `overflow-x: auto;` * combination not being compatible with native sticky in all cases. */ const stickyFix = () => { - if (!ref.current || !thead || !table || !scrollPane || !toolbar) { + if (!ref.current) { return; } - requestAnimationFrame(() => { - thead.style.top = ""; + const thead = ref.current; + const table = thead.parentNode as HTMLTableElement; + const scrollPane = table?.parentNode as HTMLDivElement; + const toolbar = scrollPane.previousSibling as HTMLDivElement | null; + requestAnimationFrame(() => { const classOverflowX = "mykn-datagrid__scrollpane--overflow-x"; const classOverflowY = "mykn-datagrid__scrollpane--overflow-y"; + // Reset. + thead.style.top = ""; + scrollPane.classList.remove(classOverflowX); + scrollPane.classList.remove(classOverflowY); + // Active conditions. const isHeightSet = Boolean(height); const isHeight100Percent = height === "100%"; // (100)% is edge case. - const isHeightExplicitlySet = isHeightSet && !isHeight100Percent; const isScrollX = - allowOverflowX && scrollPane.scrollWidth - scrollPane.clientWidth > 20; + allowOverflowX && scrollPane.scrollWidth > scrollPane.clientWidth; // Available fixes. - const shouldOverflowX = isScrollX && !isHeightExplicitlySet; - const shouldOverflowY = isHeightExplicitlySet; - const shouldStickyFix = shouldOverflowX; + const shouldOverflowX = !isHeightSet && isScrollX; + const shouldOverflowY = isHeightSet; + const shouldStickyFix = isHeight100Percent || (!height && isScrollX); // Apply overflow CSS rules using classes. - if (scrollPane.classList.contains(classOverflowX) !== shouldOverflowX) { - scrollPane.classList.toggle(classOverflowX, shouldOverflowX); - } - if (scrollPane.classList.contains(classOverflowY) !== shouldOverflowY) { - scrollPane.classList.toggle(classOverflowY, shouldOverflowY); - } + scrollPane.classList.toggle(classOverflowX, shouldOverflowX); + scrollPane.classList.toggle(classOverflowY, shouldOverflowY); // No need for fallback implementation as only `overflow-y: auto;` has to // be set. - if (!shouldStickyFix) return; + if (!shouldStickyFix) { + return; + } // Fix the sticky top behaviour. - thead.style.transform = ""; const boundingClientRect = thead.getBoundingClientRect(); const boundingTop = boundingClientRect.top; @@ -93,16 +92,10 @@ export const DataGridTHead = < // Invert the negative offset caused by scrolling and push the position // in the opposite direction, then apply some compensation for the // existing offset. - const compensation = Math.max( + const compensation = boundingTop * -1 + - (toolbar ? toolbar.clientHeight : 0) * (isHeight100Percent ? 1 : 2), - 0, - ); - - // No compensation. - if (!compensation) return; - - thead.style.top = `${compensation}px`; + (toolbar ? toolbar.clientHeight : 0) * (isHeight100Percent ? 1 : 2); + thead.style.top = compensation + "px"; }); };