mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(menu): align appearance with spec (#5361)
Aligns the menu panel appearance with [the spec](https://material.io/guidelines/components/menus.html) by: * Reducing the elevation from 8 to 3. * Adding a slight border radius. * Tweaking the animation to match the examples. Relates to #3814.
This commit is contained in:
committed by
Jeremy Elbourn
parent
78f0cecb79
commit
c20bec8b80
@@ -13,9 +13,9 @@ $mat-autocomplete-panel-below-offset: 6px !default;
|
||||
$mat-autocomplete-panel-above-offset: -24px !default;
|
||||
|
||||
.mat-autocomplete-panel {
|
||||
@include mat-menu-base();
|
||||
@include mat-menu-base(8);
|
||||
visibility: hidden;
|
||||
|
||||
|
||||
max-width: none;
|
||||
max-height: $mat-autocomplete-panel-max-height;
|
||||
position: relative;
|
||||
|
||||
@@ -13,8 +13,8 @@ $mat-menu-side-padding: 16px !default;
|
||||
$mat-menu-icon-margin: 16px !default;
|
||||
|
||||
|
||||
@mixin mat-menu-base() {
|
||||
@include mat-elevation(8);
|
||||
@mixin mat-menu-base($elevation) {
|
||||
@include mat-elevation($elevation);
|
||||
min-width: $mat-menu-overlay-min-width;
|
||||
max-width: $mat-menu-overlay-max-width;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.mat-menu-content {
|
||||
.mat-menu-panel {
|
||||
background: mat-color($background, 'card');
|
||||
}
|
||||
|
||||
|
||||
@@ -32,22 +32,23 @@ import{
|
||||
|
||||
// TODO(kara): switch to :enter and :leave once Mobile Safari is sorted out.
|
||||
export const transformMenu: AnimationTriggerMetadata = trigger('transformMenu', [
|
||||
state('showing', style({
|
||||
opacity: 1,
|
||||
transform: `scale(1)`
|
||||
state('void', style({
|
||||
opacity: 0,
|
||||
transform: 'scale(0, 0)'
|
||||
})),
|
||||
transition('void => *', [
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: `scale(0)`
|
||||
}),
|
||||
animate(`200ms cubic-bezier(0.25, 0.8, 0.25, 1)`)
|
||||
]),
|
||||
transition('* => void', [
|
||||
animate('50ms 100ms linear', style({opacity: 0}))
|
||||
])
|
||||
state('enter-start', style({
|
||||
opacity: 1,
|
||||
transform: `scale(1, 0.5)`
|
||||
})),
|
||||
state('enter', style({
|
||||
transform: 'scale(1, 1)'
|
||||
})),
|
||||
transition('void => enter-start', animate('100ms linear')),
|
||||
transition('enter-start => enter', animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
|
||||
transition('* => void', animate('150ms 50ms linear', style({opacity: 0})))
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* This animation fades in the background color and content of the menu panel
|
||||
* after its containing element is scaled in.
|
||||
@@ -56,6 +57,6 @@ export const fadeInItems: AnimationTriggerMetadata = trigger('fadeInItems', [
|
||||
state('showing', style({opacity: 1})),
|
||||
transition('void => *', [
|
||||
style({opacity: 0}),
|
||||
animate(`200ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)`)
|
||||
animate(`400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)`)
|
||||
])
|
||||
]);
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
ElementRef,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import {AnimationEvent} from '@angular/animations';
|
||||
import {MenuPositionX, MenuPositionY} from './menu-positions';
|
||||
import {throwMdMenuInvalidPositionX, throwMdMenuInvalidPositionY} from './menu-errors';
|
||||
import {MdMenuItem} from './menu-item';
|
||||
@@ -55,6 +56,9 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
|
||||
/** Config object to be passed into the menu's ngClass */
|
||||
_classList: any = {};
|
||||
|
||||
/** Current state of the panel animation. */
|
||||
_panelAnimationState: 'void' | 'enter-start' | 'enter' = 'void';
|
||||
|
||||
/** Position of the menu in the X axis. */
|
||||
@Input()
|
||||
get xPosition() { return this._xPosition; }
|
||||
@@ -161,4 +165,21 @@ export class MdMenu implements AfterContentInit, MdMenuPanel, OnDestroy {
|
||||
this._classList['mat-menu-below'] = posY === 'below';
|
||||
}
|
||||
|
||||
/** Starts the enter animation. */
|
||||
_startAnimation() {
|
||||
this._panelAnimationState = 'enter-start';
|
||||
}
|
||||
|
||||
/** Resets the panel animation to its initial state. */
|
||||
_resetAnimation() {
|
||||
this._panelAnimationState = 'void';
|
||||
}
|
||||
|
||||
/** Callback that is invoked when the panel animation completes. */
|
||||
_onAnimationDone(event: AnimationEvent) {
|
||||
// After the initial expansion is done, trigger the second phase of the enter animation.
|
||||
if (event.toState === 'enter-start') {
|
||||
this._panelAnimationState = 'enter';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
} from '../core';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {MenuPositionX, MenuPositionY} from './menu-positions';
|
||||
import {MdMenu} from './menu-directive';
|
||||
|
||||
// TODO(andrewseguin): Remove the kebab versions in favor of camelCased attribute selectors
|
||||
|
||||
@@ -110,6 +111,10 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
|
||||
this._createOverlay().attach(this._portal);
|
||||
this._subscribeToBackdrop();
|
||||
this._initMenu();
|
||||
|
||||
if (this.menu instanceof MdMenu) {
|
||||
this.menu._startAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +124,10 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
|
||||
this._overlayRef.detach();
|
||||
this._backdropSubscription.unsubscribe();
|
||||
this._resetMenu();
|
||||
|
||||
if (this.menu instanceof MdMenu) {
|
||||
this.menu._resetAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<ng-template>
|
||||
<div class="mat-menu-panel" [ngClass]="_classList" (keydown)="_handleKeydown($event)"
|
||||
(click)="_emitCloseEvent()" [@transformMenu]="'showing'" role="menu">
|
||||
<div
|
||||
class="mat-menu-panel"
|
||||
[ngClass]="_classList"
|
||||
(keydown)="_handleKeydown($event)"
|
||||
(click)="_emitCloseEvent()"
|
||||
[@transformMenu]="_panelAnimationState"
|
||||
(@transformMenu.done)="_onAnimationDone($event)"
|
||||
role="menu">
|
||||
<div class="mat-menu-content" [@fadeInItems]="'showing'">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
@import '../core/a11y/a11y';
|
||||
|
||||
$mat-menu-vertical-padding: 8px !default;
|
||||
$mat-menu-border-radius: 2px !default;
|
||||
|
||||
.mat-menu-panel {
|
||||
@include mat-menu-base();
|
||||
@include mat-menu-base(2);
|
||||
@include mat-menu-positions();
|
||||
max-height: calc(100vh - #{$mat-menu-item-height});
|
||||
border-radius: $mat-menu-border-radius;
|
||||
|
||||
@include cdk-high-contrast {
|
||||
outline: solid 1px;
|
||||
|
||||
@@ -123,7 +123,7 @@ $mat-select-trigger-underline-height: 1px !default;
|
||||
}
|
||||
|
||||
.mat-select-panel {
|
||||
@include mat-menu-base();
|
||||
@include mat-menu-base(8);
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
max-height: $mat-select-panel-max-height;
|
||||
|
||||
Reference in New Issue
Block a user