Skip to content

Commit e1d89f2

Browse files
committed
fix: scroll to selected row
1 parent b1206e6 commit e1d89f2

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

src/containers/Tenant/Diagnostics/TopQueries/TopQueriesData.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
TOP_QUERIES_SELECTED_COLUMNS_LS_KEY,
3131
} from './columns/constants';
3232
import {DEFAULT_TIME_FILTER_VALUE, TIME_FRAME_OPTIONS} from './constants';
33+
import type {ReactList} from './hooks/useScrollToSelected';
34+
import {useScrollToSelected} from './hooks/useScrollToSelected';
3335
import {useSetSelectedTopQueryRowFromParams} from './hooks/useSetSelectedTopQueryRowFromParams';
3436
import {useTopQueriesSort} from './hooks/useTopQueriesSort';
3537
import i18n from './i18n';
@@ -61,6 +63,9 @@ export const TopQueriesData = ({
6163
// null is reserved for not found state
6264
const [selectedRow, setSelectedRow] = React.useState<KeyValueRow | null | undefined>(undefined);
6365

66+
// Ref for react-list component to enable scrolling to selected row
67+
const reactListRef = React.useRef<ReactList>(null);
68+
6469
// Get columns for top queries
6570
const columns: Column<KeyValueRow>[] = React.useMemo(() => {
6671
return getTopQueriesColumns();
@@ -89,6 +94,19 @@ export const TopQueriesData = ({
8994
const rows = currentData?.resultSets?.[0]?.result;
9095
useSetSelectedTopQueryRowFromParams(setSelectedRow, rows);
9196

97+
// Enhanced table settings with dynamicInnerRef for scrolling
98+
const tableSettings = React.useMemo(
99+
() => ({
100+
...TOP_QUERIES_TABLE_SETTINGS,
101+
dynamicInnerRef: reactListRef,
102+
// Using 'uniform' type - react-list automatically calculates size from first item
103+
}),
104+
[],
105+
);
106+
107+
// Use custom hook to handle scrolling to selected row
108+
useScrollToSelected({selectedRow, rows, reactListRef});
109+
92110
const handleCloseDetails = React.useCallback(() => {
93111
setSelectedRow(undefined);
94112
}, [setSelectedRow]);
@@ -182,7 +200,7 @@ export const TopQueriesData = ({
182200
columns={columnsToShow}
183201
data={rows || []}
184202
loading={isFetching && currentData === undefined}
185-
settings={TOP_QUERIES_TABLE_SETTINGS}
203+
settings={tableSettings}
186204
onRowClick={onRowClick}
187205
rowClassName={(row) => b('row', {active: isEqual(row, selectedRow)})}
188206
sortOrder={tableSort}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
3+
import {isEqual} from 'lodash';
4+
5+
import type {KeyValueRow} from '../../../../../types/api/query';
6+
7+
// Type for react-list component
8+
export interface ReactList {
9+
scrollTo: (index: number) => void;
10+
scrollAround: (index: number) => void;
11+
getVisibleRange: () => [number, number];
12+
}
13+
14+
interface UseScrollToSelectedParams {
15+
selectedRow: KeyValueRow | null | undefined;
16+
rows: KeyValueRow[] | undefined;
17+
reactListRef: React.RefObject<ReactList>;
18+
}
19+
20+
/**
21+
* Custom hook to handle scrolling to selected row in react-list
22+
* Only scrolls if the selected item is not currently visible
23+
* When scrolling, positions the item in the middle of the viewport
24+
*/
25+
export function useScrollToSelected({selectedRow, rows, reactListRef}: UseScrollToSelectedParams) {
26+
React.useEffect(() => {
27+
if (selectedRow && rows && reactListRef.current) {
28+
const selectedIndex = rows.findIndex((row) => isEqual(row, selectedRow));
29+
if (selectedIndex !== -1) {
30+
const reactList = reactListRef.current;
31+
32+
try {
33+
const visibleRange = reactList.getVisibleRange();
34+
const [firstVisible, lastVisible] = visibleRange;
35+
36+
// Check if selected item is already visible
37+
const isVisible = selectedIndex >= firstVisible && selectedIndex <= lastVisible;
38+
39+
if (!isVisible) {
40+
// Only scroll if not visible - position in middle of viewport
41+
const visibleCount = lastVisible - firstVisible + 1;
42+
const middleOffset = Math.floor(visibleCount / 2);
43+
const targetIndex = Math.max(0, selectedIndex - middleOffset);
44+
45+
reactList.scrollTo(targetIndex);
46+
}
47+
// If already visible, don't scroll (better UX)
48+
} catch {
49+
// Fallback to scrollAround if getVisibleRange fails
50+
reactList.scrollAround(selectedIndex);
51+
}
52+
}
53+
}
54+
}, [selectedRow, rows, reactListRef]);
55+
}

src/containers/Tenant/Diagnostics/TopQueries/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const TOP_QUERIES_TABLE_SETTINGS: Settings = {
1313
...QUERY_TABLE_SETTINGS,
1414
disableSortReset: true,
1515
externalSort: true,
16+
dynamicRenderType: 'uniform', // All rows have fixed height due to FixedHeightQuery
1617
};
1718

1819
export function createQueryInfoItems(data: KeyValueRow): InfoViewerItem[] {

0 commit comments

Comments
 (0)