@@ -26,14 +26,43 @@ import Can from "src/auth/Can";
2626
2727/**
2828 * Scroll to a page element based on its key
29+ * @param {string } recordKey - The key representing the record type to scroll to
30+ * @param {Object } refs - An object containing refs for each table element on the page
31+ * @param {string } behavior - The scroll behavior
2932 */
30- const scrollToTable = ( recordKey , refs ) => {
33+ const scrollToTable = ( recordKey , refs , behavior = "smooth" ) => {
3134 const ref = refs ?. [ recordKey ] ;
35+
3236 if ( ref ?. current ) {
33- ref . current . scrollIntoView ( { behavior : "smooth" } ) ;
37+ ref . current . scrollIntoView ( { behavior } ) ;
3438 }
3539} ;
3640
41+ /**
42+ * Custom hook to scroll to a table when the hash in the URL changes. Listens for changes to the hash and
43+ * uses a ResizeObserver to ensure that the element is scrolled into view after any layout shifts.
44+ * @param {Object } props
45+ * @param {string } props.recordKeyHash - The hash from the URL representing the record key to scroll to
46+ * @param {Object } props.refs - An object containing refs for each table element on the page
47+ * */
48+ const useScrollToHash = ( { recordKeyHash, refs } ) => {
49+ useEffect ( ( ) => {
50+ if ( ! recordKeyHash ) return ;
51+
52+ const recordKey = recordKeyHash . replace ( "#" , "" ) . replaceAll ( "-" , "_" ) ;
53+ const resizeObserver = new ResizeObserver ( ( ) => {
54+ scrollToTable ( recordKey , refs , "instant" ) ;
55+ } ) ;
56+
57+ // Observe resize of every table so we keep scrolling until layout is fully populated with async data
58+ Object . values ( refs ) . forEach ( ( ref ) => {
59+ if ( ref . current ) resizeObserver . observe ( ref . current ) ;
60+ } ) ;
61+
62+ return ( ) => resizeObserver . disconnect ( ) ;
63+ } , [ recordKeyHash , refs ] ) ;
64+ } ;
65+
3766const TAG_TABLE_KEYS = [ "moped_component_tags" , "moped_tags" ] ;
3867
3968/**
@@ -73,18 +102,8 @@ const LookupsView = () => {
73102 [ ]
74103 ) ;
75104
76- /**
77- * Use the record hash from the URL, if present. This only happens once after
78- * data fetch.
79- * */
80105 let { hash : recordKeyHash , pathname } = useLocation ( ) ;
81- useEffect ( ( ) => {
82- if ( ! recordKeyHash || loading ) {
83- return ;
84- }
85- const recordKey = recordKeyHash . replace ( "#" , "" ) . replaceAll ( "-" , "_" ) ;
86- scrollToTable ( recordKey , refs ) ;
87- } , [ recordKeyHash , loading , refs ] ) ;
106+ useScrollToHash ( { recordKeyHash, refs } ) ;
88107
89108 return (
90109 < ApolloErrorHandler error = { error } >
0 commit comments