Skip to content

Commit 1bf5415

Browse files
committed
fix(select):change calculateOverlayOffsetY to address scrolling for small lists in issue #9751
1 parent e4bca63 commit 1bf5415

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

src/lib/select/select.ts

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,38 +1114,45 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
11141114
*/
11151115
private _calculateOverlayOffsetY(selectedIndex: number, scrollBuffer: number,
11161116
maxScroll: number): number {
1117-
const itemHeight = this._getItemHeight();
1118-
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
1119-
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
1120-
let optionOffsetFromPanelTop: number;
1121-
1122-
if (this._scrollTop === 0) {
1123-
optionOffsetFromPanelTop = selectedIndex * itemHeight;
1124-
} else if (this._scrollTop === maxScroll) {
1125-
const firstDisplayedIndex = this._getItemCount() - maxOptionsDisplayed;
1126-
const selectedDisplayIndex = selectedIndex - firstDisplayedIndex;
1127-
1128-
// The first item is partially out of the viewport. Therefore we need to calculate what
1129-
// portion of it is shown in the viewport and account for it in our offset.
1130-
let partialItemHeight =
1131-
itemHeight - (this._getItemCount() * itemHeight - SELECT_PANEL_MAX_HEIGHT) % itemHeight;
1132-
1133-
// Because the panel height is longer than the height of the options alone,
1134-
// there is always extra padding at the top or bottom of the panel. When
1135-
// scrolled to the very bottom, this padding is at the top of the panel and
1136-
// must be added to the offset.
1137-
optionOffsetFromPanelTop = selectedDisplayIndex * itemHeight + partialItemHeight;
1138-
} else {
1139-
// If the option was scrolled to the middle of the panel using a scroll buffer,
1140-
// its offset will be the scroll buffer minus the half height that was added to
1141-
// center it.
1142-
optionOffsetFromPanelTop = scrollBuffer - itemHeight / 2;
1143-
}
1117+
// Only enable offset for larger lists
1118+
if (this._getItemCount() > 10) {
1119+
const itemHeight = this._getItemHeight();
1120+
const optionHeightAdjustment = (itemHeight - this._triggerRect.height) / 2;
1121+
const maxOptionsDisplayed = Math.floor(SELECT_PANEL_MAX_HEIGHT / itemHeight);
1122+
let optionOffsetFromPanelTop: number;
1123+
1124+
if (this._scrollTop === 0) {
1125+
optionOffsetFromPanelTop = selectedIndex * itemHeight;
1126+
} else if (this._scrollTop === maxScroll) {
1127+
const firstDisplayedIndex = this._getItemCount() - maxOptionsDisplayed;
1128+
const selectedDisplayIndex = selectedIndex - firstDisplayedIndex;
1129+
1130+
// The first item is partially out of the viewport. Therefore we need to calculate what
1131+
// portion of it is shown in the viewport and account for it in our offset.
1132+
let partialItemHeight =
1133+
itemHeight - (this._getItemCount() * itemHeight - SELECT_PANEL_MAX_HEIGHT) % itemHeight;
1134+
1135+
// Because the panel height is longer than the height of the options alone,
1136+
// there is always extra padding at the top or bottom of the panel. When
1137+
// scrolled to the very bottom, this padding is at the top of the panel and
1138+
// must be added to the offset.
1139+
optionOffsetFromPanelTop = selectedDisplayIndex * itemHeight + partialItemHeight;
1140+
} else {
1141+
// If the option was scrolled to the middle of the panel using a scroll buffer,
1142+
// its offset will be the scroll buffer minus the half height that was added to
1143+
// center it.
1144+
optionOffsetFromPanelTop = scrollBuffer - itemHeight / 2;
1145+
}
11441146

1145-
// The final offset is the option's offset from the top, adjusted for the height
1146-
// difference, multiplied by -1 to ensure that the overlay moves in the correct
1147-
// direction up the page.
1148-
return optionOffsetFromPanelTop * -1 - optionHeightAdjustment;
1147+
// The final offset is the option's offset from the top, adjusted for the height
1148+
// difference, multiplied by -1 to ensure that the overlay moves in the correct
1149+
// direction up the page.
1150+
1151+
return optionOffsetFromPanelTop * -1 - optionHeightAdjustment;
1152+
} else {
1153+
// disable offset for smaller lists
1154+
return 0;
1155+
}
11491156
}
11501157

11511158
/**

0 commit comments

Comments
 (0)