Skip to content

fix(select): panel in multiple mode not overlapping trigger #4952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions src/lib/select/select-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,43 @@ export const transformPlaceholder: AnimationTriggerMetadata = trigger('transform
state('floating-ltr', style({
top: '-22px',
left: '-2px',
transform: `scale(0.75)`
transform: 'scale(0.75)'
})),
state('floating-rtl', style({
top: '-22px',
left: '2px',
transform: `scale(0.75)`
transform: 'scale(0.75)'
})),
transition('* => *', animate(`400ms cubic-bezier(0.25, 0.8, 0.25, 1)`))
transition('* => *', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
]);

/**
* This animation transforms the select's overlay panel on and off the page.
*
* When the panel is attached to the DOM, it expands its width 32px, scales it up to
* 100% on the Y axis, fades in its border, and translates slightly up and to the
* When the panel is attached to the DOM, it expands its width by the amount of padding, scales it
* up to 100% on the Y axis, fades in its border, and translates slightly up and to the
* side to ensure the option text correctly overlaps the trigger text.
*
* When the panel is removed from the DOM, it simply fades out linearly.
*/
export const transformPanel: AnimationTriggerMetadata = trigger('transformPanel', [
state('showing', style({
opacity: 1,
minWidth: 'calc(100% + 32px)',
transform: `scaleY(1)`
minWidth: 'calc(100% + 32px)', // 32px = 2 * 16px padding
transform: 'scaleY(1)'
})),
state('showing-multiple', style({
opacity: 1,
minWidth: 'calc(100% + 64px)', // 64px = 48px padding on the left + 16px padding on the right
transform: 'scaleY(1)'
})),
transition('void => *', [
style({
opacity: 0,
minWidth: '100%',
transform: `scaleY(0)`
transform: 'scaleY(0)'
}),
animate(`150ms cubic-bezier(0.25, 0.8, 0.25, 1)`)
animate('150ms cubic-bezier(0.25, 0.8, 0.25, 1)')
]),
transition('* => void', [
animate('250ms 100ms linear', style({opacity: 0}))
Expand All @@ -66,10 +71,10 @@ export const transformPanel: AnimationTriggerMetadata = trigger('transformPanel'
* select's options. It is time delayed to occur 100ms after the overlay
* panel has transformed in.
*/
export const fadeInContent: AnimationTriggerMetadata = trigger('fadeInContent', [
export const fadeInContent: AnimationTriggerMetadata = trigger('fadeInContent', [
state('showing', style({opacity: 1})),
transition('void => showing', [
style({opacity: 0}),
animate(`150ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)`)
animate('150ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)')
])
]);
28 changes: 22 additions & 6 deletions src/lib/select/select.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,28 @@
<span class="mat-select-underline"></span>
</div>

<ng-template cdk-connected-overlay [origin]="origin" [open]="panelOpen" hasBackdrop (backdropClick)="close()"
backdropClass="cdk-overlay-transparent-backdrop" [positions]="_positions" [minWidth]="_triggerWidth"
[offsetY]="_offsetY" (attach)="_onAttached()" (detach)="close()">
<div class="mat-select-panel {{ 'mat-' + color }}" [ngClass]="panelClass" [@transformPanel]="'showing'"
(@transformPanel.done)="_onPanelDone()" (keydown)="_handlePanelKeydown($event)"
[style.transformOrigin]="_transformOrigin" [class.mat-select-panel-done-animating]="_panelDoneAnimating">
<ng-template
cdk-connected-overlay
hasBackdrop
backdropClass="cdk-overlay-transparent-backdrop"
[origin]="origin"
[open]="panelOpen"
[positions]="_positions"
[minWidth]="_triggerWidth"
[offsetY]="_offsetY"
(backdropClick)="close()"
(attach)="_onAttached()"
(detach)="close()">

<div
class="mat-select-panel {{ 'mat-' + color }}"
[ngClass]="panelClass"
[@transformPanel]="multiple ? 'showing-multiple' : 'showing'"
(@transformPanel.done)="_onPanelDone()"
(keydown)="_handlePanelKeydown($event)"
[style.transformOrigin]="_transformOrigin"
[class.mat-select-panel-done-animating]="_panelDoneAnimating">

<div class="mat-select-content" [@fadeInContent]="'showing'" (@fadeInContent.done)="_onFadeInDone()">
<ng-content></ng-content>
</div>
Expand Down
8 changes: 5 additions & 3 deletions src/lib/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,16 +838,18 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
const overlayRect = this.overlayDir.overlayRef.overlayElement.getBoundingClientRect();
const viewportRect = this._viewportRuler.getViewportRect();
const isRtl = this._isRtl();
const paddingWidth = this.multiple ? SELECT_MULTIPLE_PANEL_PADDING_X + SELECT_PANEL_PADDING_X :
SELECT_PANEL_PADDING_X * 2;

let offsetX = this.multiple ? SELECT_MULTIPLE_PANEL_PADDING_X : SELECT_PANEL_PADDING_X;

if (!isRtl) {
offsetX *= -1;
}

const leftOverflow = 0 - (overlayRect.left + offsetX
- (isRtl ? SELECT_PANEL_PADDING_X * 2 : 0));
const leftOverflow = 0 - (overlayRect.left + offsetX - (isRtl ? paddingWidth : 0));
const rightOverflow = overlayRect.right + offsetX - viewportRect.width
+ (isRtl ? 0 : SELECT_PANEL_PADDING_X * 2);
+ (isRtl ? 0 : paddingWidth);

if (leftOverflow > 0) {
offsetX += leftOverflow + SELECT_PANEL_VIEWPORT_PADDING;
Expand Down