-
Notifications
You must be signed in to change notification settings - Fork 228
Expand file tree
/
Copy pathuseScrollIntoView.tsx
More file actions
30 lines (29 loc) · 1.12 KB
/
useScrollIntoView.tsx
File metadata and controls
30 lines (29 loc) · 1.12 KB
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
import type { RefObject } from "react";
import { useEffect } from "react";
export function useScrollIntoView<T>(
selectedElement: T | undefined,
selectedElementRef: RefObject<HTMLElement | undefined>,
) {
useEffect(() => {
const element = selectedElementRef.current;
if (!element) {
return;
}
const rect = element.getBoundingClientRect();
// The selected item's bounding box might be on screen, but hidden underneath the sticky header
// which overlaps the table view. As a workaround we hardcode a fixed distance from the top which
// we consider to be obscured. It does not have to exact, as it's just a threshold for when to scroll.
const heightOfStickyHeader = 30;
if (rect.top < heightOfStickyHeader || rect.bottom > window.innerHeight) {
element.scrollIntoView({
block: "center", // vertically align to center
});
}
if (rect.left < 0 || rect.right > window.innerWidth) {
element.scrollIntoView({
block: "nearest",
inline: "nearest", // horizontally align as little as possible
});
}
}, [selectedElement, selectedElementRef]);
}