Skip to content

Commit c0034d3

Browse files
crisbetoandrewseguin
authored andcommitted
fix(autocomplete): top option group not scrolled into view when going up (#16343)
Fixes the case where the user won't be able to see the top option group when reaching the first option via the arrow keys. (cherry picked from commit f797cac)
1 parent 8158754 commit c0034d3

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -500,14 +500,21 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, AfterViewIn
500500
const labelCount = _countGroupLabelsBeforeOption(index,
501501
this.autocomplete.options, this.autocomplete.optionGroups);
502502

503-
const newScrollPosition = _getOptionScrollPosition(
504-
index + labelCount,
505-
AUTOCOMPLETE_OPTION_HEIGHT,
506-
this.autocomplete._getScrollTop(),
507-
AUTOCOMPLETE_PANEL_HEIGHT
508-
);
509-
510-
this.autocomplete._setScrollTop(newScrollPosition);
503+
if (index === 0 && labelCount === 1) {
504+
// If we've got one group label before the option and we're at the top option,
505+
// scroll the list to the top. This is better UX than scrolling the list to the
506+
// top of the option, because it allows the user to read the top group's label.
507+
this.autocomplete._setScrollTop(0);
508+
} else {
509+
const newScrollPosition = _getOptionScrollPosition(
510+
index + labelCount,
511+
AUTOCOMPLETE_OPTION_HEIGHT,
512+
this.autocomplete._getScrollTop(),
513+
AUTOCOMPLETE_PANEL_HEIGHT
514+
);
515+
516+
this.autocomplete._setScrollTop(newScrollPosition);
517+
}
511518
}
512519

513520
/**

src/material/autocomplete/autocomplete.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,28 @@ describe('MatAutocomplete', () => {
13231323
expect(container.scrollTop)
13241324
.toBe(96, 'Expected panel to scroll up when option is above panel.');
13251325
}));
1326+
1327+
it('should scroll back to the top when reaching the first option with preceding group label',
1328+
fakeAsync(() => {
1329+
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
1330+
tick();
1331+
fixture.detectChanges();
1332+
expect(container.scrollTop).toBe(0, 'Expected the panel not to scroll.');
1333+
1334+
// Press the down arrow five times.
1335+
[1, 2, 3, 4, 5].forEach(() => {
1336+
fixture.componentInstance.trigger._handleKeydown(DOWN_ARROW_EVENT);
1337+
tick();
1338+
});
1339+
1340+
// Press the up arrow five times.
1341+
[1, 2, 3, 4, 5].forEach(() => {
1342+
fixture.componentInstance.trigger._handleKeydown(UP_ARROW_EVENT);
1343+
tick();
1344+
});
1345+
1346+
expect(container.scrollTop).toBe(0, 'Expected panel to be scrolled to the top.');
1347+
}));
13261348
});
13271349

13281350
describe('aria', () => {

0 commit comments

Comments
 (0)