Skip to content

Commit

Permalink
[Select] Flag to optionally scroll to active item for select componen…
Browse files Browse the repository at this point in the history
…ts (#3096)

* Flag to optionally scroll to active item for select components

* Respect click and keyboard interactions

* Change docs

* edit prop docs

* add uncontrolled note
  • Loading branch information
jscheiny authored and giladgray committed Nov 15, 2018
1 parent 20c7897 commit 12d1729
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
10 changes: 10 additions & 0 deletions packages/select/src/common/listItemsProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ export interface IListItemsProps<T> extends IProps {
*/
resetOnSelect?: boolean;

/**
* When `activeItem` is controlled, whether the active item should _always_
* be scrolled into view when the prop changes. If `false`, only changes
* that result from built-in interactions (clicking, querying, or using
* arrow keys) will scroll the active item into view. Ignored if the
* `activeItem` prop is omitted (uncontrolled behavior).
* @default true
*/
scrollToActiveItem?: boolean;

/**
* Query string passed to `itemListPredicate` or `itemPredicate` to filter items.
* This value is controlled: its state must be managed externally by attaching an `onChange`
Expand Down
16 changes: 16 additions & 0 deletions packages/select/src/components/query-list/queryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ export class QueryList<T> extends React.Component<IQueryListProps<T>, IQueryList
*/
private shouldCheckActiveItemInViewport = false;

/**
* The item that we expect to be the next selected active item (based on click
* or key interactions). When scrollToActiveItem = false, used to detect if
* an unexpected external change to the active item has been made.
*/
private expectedNextActiveItem: T | null = null;

public constructor(props: IQueryListProps<T>, context?: any) {
super(props, context);
const { query = "" } = this.props;
Expand Down Expand Up @@ -152,6 +159,14 @@ export class QueryList<T> extends React.Component<IQueryListProps<T>, IQueryList
}

public scrollActiveItemIntoView() {
const scrollToActiveItem = this.props.scrollToActiveItem !== false;
const externalChangeToActiveItem = this.expectedNextActiveItem !== this.props.activeItem;
this.expectedNextActiveItem = null;

if (!scrollToActiveItem && externalChangeToActiveItem) {
return;
}

const activeElement = this.getActiveElement();
if (this.itemsParentRef != null && activeElement != null) {
const { offsetTop: activeTop, offsetHeight: activeHeight } = activeElement;
Expand Down Expand Up @@ -294,6 +309,7 @@ export class QueryList<T> extends React.Component<IQueryListProps<T>, IQueryList
}

private setActiveItem(activeItem: T | null) {
this.expectedNextActiveItem = activeItem;
if (this.props.activeItem === undefined) {
// indicate that the active item may need to be scrolled into view after update.
this.shouldCheckActiveItemInViewport = true;
Expand Down

1 comment on commit 12d1729

@blueprint-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Select] Flag to optionally scroll to active item for select components (#3096)

Previews: documentation | landing | table

Please sign in to comment.