Skip to content

Commit

Permalink
fix(Select): correctly scroll to active element (#1853)
Browse files Browse the repository at this point in the history
  • Loading branch information
ValeraS authored Sep 12, 2024
1 parent a1678b6 commit d6c512a
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 8 deletions.
19 changes: 14 additions & 5 deletions src/components/List/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import './List.scss';

const b = block('list');
const DEFAULT_ITEM_HEIGHT = 28;
const DEFAULT_PAGE_SIZE = 10;

type ListState<T> = {
items: ListProps<T>['items'];
Expand Down Expand Up @@ -224,11 +225,11 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
break;
}
case 'PageDown': {
this.handleKeyMove(event, pageSize!);
this.handleKeyMove(event, pageSize ?? DEFAULT_PAGE_SIZE);
break;
}
case 'PageUp': {
this.handleKeyMove(event, -pageSize!);
this.handleKeyMove(event, -(pageSize ?? DEFAULT_PAGE_SIZE));
break;
}
case 'Home': {
Expand Down Expand Up @@ -280,13 +281,15 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
private renderItem = ({
index,
style,
height,
provided,
isDragging,
}: {
index: number;
style?: React.CSSProperties;
provided?: DraggableProvided;
isDragging?: boolean;
height?: number;
}) => {
const {sortHandleAlign, role} = this.props;
const {items, activeItem} = this.state;
Expand All @@ -301,6 +304,7 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
<ListItem
key={index}
style={style}
height={height}
itemIndex={index}
item={item}
sortable={sortable}
Expand Down Expand Up @@ -388,6 +392,7 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
ref={this.refContainer}
itemCount={items.length}
provided={droppableProvided}
onScrollToItem={this.props.onScrollToItem}
>
{items.map((_item, index) => {
return (
Expand All @@ -404,7 +409,7 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
index,
isDragging: snapshot.isDragging,
provided,
style: {height: this.getItemHeight(index)},
height: this.getItemHeight(index),
});
}}
</Draggable>
Expand All @@ -418,9 +423,13 @@ export class List<T = unknown> extends React.Component<ListProps<T>, ListState<T
}

return (
<SimpleContainer itemCount={items.length} ref={this.refContainer}>
<SimpleContainer
itemCount={items.length}
ref={this.refContainer}
onScrollToItem={this.props.onScrollToItem}
>
{items.map((_item, index) =>
this.renderItem({index, style: {height: this.getItemHeight(index)}}),
this.renderItem({index, height: this.getItemHeight(index)}),
)}
</SimpleContainer>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/List/components/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ function getStyle(provided?: DraggableProvided, style?: React.CSSProperties) {
};
}

export class ListItem<T = unknown> extends React.Component<ListItemProps<T>> {
export class ListItem<T = unknown> extends React.PureComponent<ListItemProps<T>> {
private static publishEvent = eventBroker.withEventPublisher('List');

node: HTMLDivElement | null = null;

render() {
const {
item,
height,
style,
sortable,
sortHandleAlign,
Expand All @@ -49,6 +50,7 @@ export class ListItem<T = unknown> extends React.Component<ListItemProps<T>> {
react-window has a bug where in rtl it setting "right" to 0 instead of undefined.
*/
const fixedStyle = {
height,
...style,
right: undefined,
};
Expand Down
5 changes: 4 additions & 1 deletion src/components/List/components/SimpleContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {ListItem} from './ListItem';
export type SimpleContainerProps = React.PropsWithChildren<{
itemCount: number;
provided?: DroppableProvided;
onScrollToItem?: (node: HTMLElement) => boolean;
}>;

type RefsList = Record<number, React.RefObject<ListItem>>;
Expand Down Expand Up @@ -64,7 +65,9 @@ export class SimpleContainer extends React.Component<SimpleContainerProps, Simpl
const node = listItem.getNode();

if (node) {
node.scrollIntoView?.({block: 'nearest'});
if (!this.props.onScrollToItem?.(node)) {
node.scrollIntoView?.({block: 'nearest'});
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/List/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type ListProps<T = unknown> = QAProps & {
onLoadMore?: () => void;
onChangeActive?: (index?: number) => void;
id?: string;
onScrollToItem?: (node: HTMLElement) => boolean;
};

export type ListItemProps<T> = {
Expand All @@ -64,6 +65,7 @@ export type ListItemProps<T> = {
sortable?: boolean;
sortHandleAlign?: ListSortHandleAlign;
style?: React.CSSProperties;
height?: number;
onActivate: (index?: number) => void;
renderItem?: ListProps<T>['renderItem'];
onClick?: ListProps<T>['onItemClick'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ $xl-right-padding: '12px';

&:not(#{$block}_virtualized) {
overflow: auto;
position: relative;
}

&_mobile {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Select/components/SelectList/SelectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React from 'react';
import {List} from '../../../List';
import {SelectQa, selectListBlock} from '../../constants';
import type {SelectOption, SelectProps} from '../../types';
import {getOptionsHeight, getPopupItemHeight} from '../../utils';
import {getOptionsHeight, getPopupItemHeight, scrollToItem} from '../../utils';
import type {FlattenOption, GroupTitleItem} from '../../utils';

import {GroupLabel} from './GroupLabel';
Expand Down Expand Up @@ -152,6 +152,7 @@ export const SelectList = React.forwardRef<List<FlattenOption>, SelectListProps>
activeItemIndex={activeIndex}
onChangeActive={onChangeActive}
deactivateOnLeave={false}
onScrollToItem={scrollToItem}
/>
);
});
Expand Down
19 changes: 19 additions & 0 deletions src/components/Select/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,22 @@ export const getFilteredFlattenOptions = (args: {
return acc;
}, [] as FlattenOption[]);
};

export function scrollToItem(node: HTMLElement) {
const container = node.offsetParent;
if (container instanceof HTMLElement) {
const height = container.offsetHeight;
const scrollTop = container.scrollTop;

const top = node.offsetTop;
const bottom = top + node.offsetHeight;

if (bottom >= scrollTop + height) {
container.scrollTo({top: top - height + node.offsetHeight});
} else if (top <= scrollTop) {
container.scrollTo({top});
}
}

return true;
}

0 comments on commit d6c512a

Please sign in to comment.