mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix selecting items always scrolling to top (#5728)
This commit is contained in:
parent
657119b22b
commit
7ab3d419b3
@ -0,0 +1,355 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`VirtualList renders 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="VirtualList"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="list"
|
||||||
|
style="position: relative; height: 45px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="height: 4545px; width: 100%;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-0"
|
||||||
|
style="position: absolute; left: 0px; top: 0px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-1"
|
||||||
|
style="position: absolute; left: 0px; top: 15px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-1
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-2"
|
||||||
|
style="position: absolute; left: 0px; top: 30px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-2
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-3"
|
||||||
|
style="position: absolute; left: 0px; top: 45px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-4"
|
||||||
|
style="position: absolute; left: 0px; top: 60px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-4
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-5"
|
||||||
|
style="position: absolute; left: 0px; top: 75px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-5
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-6"
|
||||||
|
style="position: absolute; left: 0px; top: 90px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-6
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-7"
|
||||||
|
style="position: absolute; left: 0px; top: 105px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-7
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-8"
|
||||||
|
style="position: absolute; left: 0px; top: 120px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-8
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-9"
|
||||||
|
style="position: absolute; left: 0px; top: 135px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-9
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-10"
|
||||||
|
style="position: absolute; left: 0px; top: 150px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-11"
|
||||||
|
style="position: absolute; left: 0px; top: 165px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-11
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-12"
|
||||||
|
style="position: absolute; left: 0px; top: 180px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-12
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`VirtualList when non-visable item is selected renders 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="VirtualList"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="list"
|
||||||
|
style="position: relative; height: 45px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="height: 3530px; width: 100%;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-19"
|
||||||
|
style="position: absolute; left: 0px; top: 285px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-19
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-20"
|
||||||
|
style="position: absolute; left: 0px; top: 300px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-21"
|
||||||
|
style="position: absolute; left: 0px; top: 315px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-21
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-22"
|
||||||
|
style="position: absolute; left: 0px; top: 330px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-22
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-23"
|
||||||
|
style="position: absolute; left: 0px; top: 345px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-23
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-24"
|
||||||
|
style="position: absolute; left: 0px; top: 360px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-24
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-25"
|
||||||
|
style="position: absolute; left: 0px; top: 375px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-25
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-26"
|
||||||
|
style="position: absolute; left: 0px; top: 390px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-26
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-27"
|
||||||
|
style="position: absolute; left: 0px; top: 405px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-27
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-28"
|
||||||
|
style="position: absolute; left: 0px; top: 420px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-28
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-29"
|
||||||
|
style="position: absolute; left: 0px; top: 435px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-29
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-30"
|
||||||
|
style="position: absolute; left: 0px; top: 450px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-31"
|
||||||
|
style="position: absolute; left: 0px; top: 465px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-31
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-32"
|
||||||
|
style="position: absolute; left: 0px; top: 480px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-32
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-33"
|
||||||
|
style="position: absolute; left: 0px; top: 495px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-33
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-34"
|
||||||
|
style="position: absolute; left: 0px; top: 510px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-34
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-35"
|
||||||
|
style="position: absolute; left: 0px; top: 525px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-35
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-36"
|
||||||
|
style="position: absolute; left: 0px; top: 540px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-36
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-37"
|
||||||
|
style="position: absolute; left: 0px; top: 555px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-37
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-38"
|
||||||
|
style="position: absolute; left: 0px; top: 570px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-38
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-39"
|
||||||
|
style="position: absolute; left: 0px; top: 585px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-39
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-40"
|
||||||
|
style="position: absolute; left: 0px; top: 600px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-41"
|
||||||
|
style="position: absolute; left: 0px; top: 615px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-41
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`VirtualList when visible item is selected renders 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="VirtualList"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="list"
|
||||||
|
style="position: relative; height: 45px; width: 100%; overflow: auto; will-change: transform; direction: ltr;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="height: 4545px; width: 100%;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-0"
|
||||||
|
style="position: absolute; left: 0px; top: 0px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-1"
|
||||||
|
style="position: absolute; left: 0px; top: 15px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-1
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-2"
|
||||||
|
style="position: absolute; left: 0px; top: 30px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-2
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-3"
|
||||||
|
style="position: absolute; left: 0px; top: 45px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-4"
|
||||||
|
style="position: absolute; left: 0px; top: 60px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-4
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-5"
|
||||||
|
style="position: absolute; left: 0px; top: 75px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-5
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-6"
|
||||||
|
style="position: absolute; left: 0px; top: 90px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-6
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-7"
|
||||||
|
style="position: absolute; left: 0px; top: 105px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-7
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-8"
|
||||||
|
style="position: absolute; left: 0px; top: 120px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-8
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-9"
|
||||||
|
style="position: absolute; left: 0px; top: 135px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-9
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-10"
|
||||||
|
style="position: absolute; left: 0px; top: 150px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-11"
|
||||||
|
style="position: absolute; left: 0px; top: 165px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-11
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-testid="some-id-12"
|
||||||
|
style="position: absolute; left: 0px; top: 180px; height: 15px; width: 100%;"
|
||||||
|
>
|
||||||
|
some-id-12
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
81
src/renderer/components/virtual-list/virtual-list.test.tsx
Normal file
81
src/renderer/components/virtual-list/virtual-list.test.tsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { RenderResult } from "@testing-library/react";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import { VirtualList } from "./virtual-list";
|
||||||
|
|
||||||
|
const generateListOfIdObjects = (count: number) => [...new Array(count)].map((v, index) => ({
|
||||||
|
getId() {
|
||||||
|
return `some-id-${index}`;
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
const generateListOfRowHeights = (count: number, size: number) => [...new Array(count)].map(() => size);
|
||||||
|
const renderList = (selectedId?: string) => (
|
||||||
|
<VirtualList
|
||||||
|
items={generateListOfIdObjects(100)}
|
||||||
|
rowHeights={generateListOfRowHeights(100, 15)}
|
||||||
|
fixedHeight={45}
|
||||||
|
selectedItemId={selectedId}
|
||||||
|
getRow={(id) => <div data-testid={id}>{id}</div>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe("VirtualList", () => {
|
||||||
|
let result: RenderResult;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
result = render(renderList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the first item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-0")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the second item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-1")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the third item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-2")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when non-visable item is selected", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.rerender(renderList("some-id-30"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows selected item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-30")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show the first item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-0")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when visible item is selected", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.rerender(renderList("some-id-2"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows selected item", () => {
|
||||||
|
expect(result.queryByTestId("some-id-2")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -14,7 +14,6 @@ import type { Align, ListChildComponentProps, ListOnScrollProps } from "react-wi
|
|||||||
import { VariableSizeList } from "react-window";
|
import { VariableSizeList } from "react-window";
|
||||||
import { cssNames, noop } from "../../utils";
|
import { cssNames, noop } from "../../utils";
|
||||||
import type { TableRowProps } from "../table/table-row";
|
import type { TableRowProps } from "../table/table-row";
|
||||||
import debounce from "lodash/debounce";
|
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import AutoSizer from "react-virtualized-auto-sizer";
|
import AutoSizer from "react-virtualized-auto-sizer";
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ function VirtualListInner<T extends { getId(): string } | string>({
|
|||||||
const listRef = createRef<VariableSizeList>();
|
const listRef = createRef<VariableSizeList>();
|
||||||
const prevItems = useRef(items);
|
const prevItems = useRef(items);
|
||||||
const prevRowHeights = useRef(rowHeights);
|
const prevRowHeights = useRef(rowHeights);
|
||||||
const scrollToSelectedItem = useCallback(debounce(() => {
|
const scrollToSelectedItem = useCallback(() => {
|
||||||
if (!selectedItemId) {
|
if (!selectedItemId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -71,9 +70,9 @@ function VirtualListInner<T extends { getId(): string } | string>({
|
|||||||
));
|
));
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
listRef.current?.scrollToItem(index, "start");
|
listRef.current?.scrollToItem(index, "smart");
|
||||||
}
|
}
|
||||||
}), [selectedItemId, [items]]);
|
}, [selectedItemId, [items]]);
|
||||||
const getItemSize = (index: number) => rowHeights[index];
|
const getItemSize = (index: number) => rowHeights[index];
|
||||||
|
|
||||||
useImperativeHandle(forwardedRef, () => ({
|
useImperativeHandle(forwardedRef, () => ({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user