Skip to content

feat(menu): align with 2018 material design spec #12331

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 1 commit into from
Aug 31, 2018
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
2 changes: 1 addition & 1 deletion e2e/components/menu-e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('menu', () => {
await expectAlignedWith(page.menu(), '#trigger');
});

it('should align overlay end to origin end when x-position is "before"', async() => {
it('should align overlay end to origin end when x-position is "before"', async () => {
page.beforeTrigger().click();

const trigger = await page.beforeTrigger().getLocation();
Expand Down
12 changes: 6 additions & 6 deletions src/demo-app/menu/menu-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -137,31 +137,31 @@

<div class="demo-menu">
<div class="demo-menu-section">
<p>overlapTrigger: false</p>
<p>overlapTrigger: true</p>

<mat-toolbar>
<button mat-icon-button [mat-menu-trigger-for]="menuOverlay">
<mat-icon>more_vert</mat-icon>
</button>
</mat-toolbar>

<mat-menu [overlapTrigger]="false" #menuOverlay="matMenu">
<mat-menu [overlapTrigger]="true" #menuOverlay="matMenu">
<button mat-menu-item *ngFor="let item of items" [disabled]="item.disabled">
{{ item.text }}
</button>
</mat-menu>
</div>
<div class="demo-menu-section">
<p>
Position x: before, overlapTrigger: false
Position x: before, overlapTrigger: true
</p>
<mat-toolbar class="demo-end-icon">
<button mat-icon-button [mat-menu-trigger-for]="posXMenuOverlay">
<mat-icon>more_vert</mat-icon>
</button>
</mat-toolbar>

<mat-menu xPosition="before" [overlapTrigger]="false" #posXMenuOverlay="matMenu">
<mat-menu xPosition="before" [overlapTrigger]="true" #posXMenuOverlay="matMenu">
<button mat-menu-item *ngFor="let item of iconItems" [disabled]="item.disabled">
<mat-icon>{{ item.icon }}</mat-icon>
{{ item.text }}
Expand All @@ -170,15 +170,15 @@
</div>
<div class="demo-menu-section">
<p>
Position y: above, overlapTrigger: false
Position y: above, overlapTrigger: true
</p>
<mat-toolbar>
<button mat-icon-button [mat-menu-trigger-for]="posYMenuOverlay">
<mat-icon>more_vert</mat-icon>
</button>
</mat-toolbar>

<mat-menu yPosition="above" [overlapTrigger]="false" #posYMenuOverlay="matMenu">
<mat-menu yPosition="above" [overlapTrigger]="true" #posYMenuOverlay="matMenu">
<button mat-menu-item *ngFor="let item of items" [disabled]="item.disabled">
{{ item.text }}
</button>
Expand Down
18 changes: 14 additions & 4 deletions src/e2e-app/menu/menu-e2e.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<button [matMenuTriggerFor]="menu" id="trigger">TRIGGER</button>
<button [matMenuTriggerFor]="menu" id="trigger-two">TRIGGER 2</button>

<mat-menu #menu="matMenu" yPosition="below" class="custom">
<mat-menu #menu="matMenu" yPosition="below" class="custom" overlapTrigger>
<button mat-menu-item (click)="selected='one'">One</button>
<button mat-menu-item (click)="selected='two'">Two</button>
<button mat-menu-item (click)="selected='three'" disabled>Three</button>
Expand All @@ -15,20 +15,30 @@
<button [matMenuTriggerFor]="beforeMenu" id="before-t">
BEFORE
</button>
<mat-menu xPosition="before" yPosition="below" class="before" #beforeMenu="matMenu">
<mat-menu
xPosition="before"
yPosition="below"
class="before"
#beforeMenu="matMenu"
overlapTrigger>
<button mat-menu-item>Item</button>
</mat-menu>

<div class="bottom-row">
<button [matMenuTriggerFor]="aboveMenu" id="above-t">ABOVE</button>
<mat-menu yPosition="above" class="above" #aboveMenu="matMenu">
<mat-menu yPosition="above" class="above" #aboveMenu="matMenu" overlapTrigger>
<button mat-menu-item>Item</button>
</mat-menu>

<button [matMenuTriggerFor]="combined" id="combined-t">
BOTH
</button>
<mat-menu xPosition="before" yPosition="above" class="combined" #combined="matMenu">
<mat-menu
xPosition="before"
yPosition="above"
class="combined"
#combined="matMenu"
overlapTrigger>
<button mat-menu-item>Item</button>
</mat-menu>

Expand Down
6 changes: 3 additions & 3 deletions src/lib/menu/_menu-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
@mixin mat-menu-typography($config) {
.mat-menu-item {
font: {
family: mat-font-family($config, subheading-2);
size: mat-font-size($config, subheading-2);
weight: mat-font-weight($config, subheading-2);
family: mat-font-family($config, body-1);
size: mat-font-size($config, body-1);
weight: mat-font-weight($config, body-1);
}
}
}
19 changes: 5 additions & 14 deletions src/lib/menu/menu-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import{
transition,
query,
group,
sequence,
AnimationTriggerMetadata,
} from '@angular/animations';

Expand All @@ -38,21 +37,13 @@ export const matMenuAnimations: {
transformMenu: trigger('transformMenu', [
state('void', style({
opacity: 0,
// This starts off from 0.01, instead of 0, because there's an issue in the Angular animations
// as of 4.2, which causes the animation to be skipped if it starts from 0.
transform: 'scale(0.01, 0.01)'
transform: 'scale(0.8)'
})),
transition('void => enter', sequence([
query('.mat-menu-content', style({opacity: 0})),
animate('100ms linear', style({opacity: 1, transform: 'scale(1, 0.5)'})),
group([
query('.mat-menu-content', animate('400ms cubic-bezier(0.55, 0, 0.55, 0.2)',
style({opacity: 1})
)),
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({transform: 'scale(1, 1)'})),
])
transition('void => enter', group([
query('.mat-menu-content', animate('100ms linear', style({opacity: 1}))),
animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({transform: 'scale(1)'})),
])),
transition('* => void', animate('150ms 50ms linear', style({opacity: 0})))
transition('* => void', animate('100ms 25ms linear', style({opacity: 0})))
]),


Expand Down
4 changes: 2 additions & 2 deletions src/lib/menu/menu-directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const MAT_MENU_DEFAULT_OPTIONS =
/** @docs-private */
export function MAT_MENU_DEFAULT_OPTIONS_FACTORY(): MatMenuDefaultOptions {
return {
overlapTrigger: true,
overlapTrigger: false,
xPosition: 'after',
yPosition: 'below',
backdropClass: 'cdk-overlay-transparent-backdrop',
Expand All @@ -79,7 +79,7 @@ export function MAT_MENU_DEFAULT_OPTIONS_FACTORY(): MatMenuDefaultOptions {
* Start elevation for the menu panel.
* @docs-private
*/
const MAT_MENU_BASE_ELEVATION = 2;
const MAT_MENU_BASE_ELEVATION = 4;


@Component({
Expand Down
4 changes: 2 additions & 2 deletions src/lib/menu/menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
@import '../../cdk/a11y/a11y';

$mat-menu-vertical-padding: 8px !default;
$mat-menu-border-radius: 2px !default;
$mat-menu-border-radius: 4px !default;
$mat-menu-submenu-indicator-size: 10px !default;

.mat-menu-panel {
@include mat-menu-base(2);
@include mat-menu-base(4);
max-height: calc(100vh - #{$mat-menu-item-height});
border-radius: $mat-menu-border-radius;
outline: 0;
Expand Down
36 changes: 16 additions & 20 deletions src/lib/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ describe('MatMenu', () => {
let panel = overlayContainerElement.querySelector('.mat-menu-panel') as HTMLElement;

expect(Math.floor(panel.getBoundingClientRect().bottom))
.toBe(Math.floor(trigger.getBoundingClientRect().bottom), 'Expected menu to open above');
.toBe(Math.floor(trigger.getBoundingClientRect().top), 'Expected menu to open above');

fixture.componentInstance.trigger.closeMenu();
fixture.detectChanges();
Expand All @@ -625,7 +625,7 @@ describe('MatMenu', () => {
panel = overlayContainerElement.querySelector('.mat-menu-panel') as HTMLElement;

expect(Math.floor(panel.getBoundingClientRect().top))
.toBe(Math.floor(trigger.getBoundingClientRect().top), 'Expected menu to open below');
.toBe(Math.floor(trigger.getBoundingClientRect().bottom), 'Expected menu to open below');
});

});
Expand Down Expand Up @@ -658,7 +658,7 @@ describe('MatMenu', () => {

// The y-position of the overlay should be unaffected, as it can already fit vertically
expect(Math.floor(overlayRect.top))
.toBe(Math.floor(triggerRect.top),
.toBe(Math.floor(triggerRect.bottom),
`Expected menu top position to be unchanged if it can fit in the viewport.`);
});

Expand All @@ -678,11 +678,8 @@ describe('MatMenu', () => {
const triggerRect = trigger.getBoundingClientRect();
const overlayRect = overlayPane.getBoundingClientRect();

// In "above" position, the bottom edges of the overlay and the origin are aligned.
// To find the overlay top, subtract the menu height from the origin's bottom edge.
const expectedTop = triggerRect.bottom - overlayRect.height;
expect(Math.floor(overlayRect.top))
.toBe(Math.floor(expectedTop),
expect(Math.floor(overlayRect.bottom))
.toBe(Math.floor(triggerRect.top),
`Expected menu to open in "above" position if "below" position wouldn't fit.`);

// The x-position of the overlay should be unaffected, as it can already fit horizontally
Expand All @@ -709,14 +706,13 @@ describe('MatMenu', () => {
const overlayRect = overlayPane.getBoundingClientRect();

const expectedLeft = triggerRect.right - overlayRect.width;
const expectedTop = triggerRect.bottom - overlayRect.height;

expect(Math.floor(overlayRect.left))
.toBe(Math.floor(expectedLeft),
`Expected menu to open in "before" position if "after" position wouldn't fit.`);

expect(Math.floor(overlayRect.top))
.toBe(Math.floor(expectedTop),
expect(Math.floor(overlayRect.bottom))
.toBe(Math.floor(triggerRect.top),
`Expected menu to open in "above" position if "below" position wouldn't fit.`);
});

Expand All @@ -740,7 +736,7 @@ describe('MatMenu', () => {
// As designated "above" position won't fit on screen, the menu should fall back
// to "below" mode, where the top edges of the overlay and trigger are aligned.
expect(Math.floor(overlayRect.top))
.toBe(Math.floor(triggerRect.top),
.toBe(Math.floor(triggerRect.bottom),
`Expected menu to open in "below" position if "above" position wouldn't fit.`);
});

Expand Down Expand Up @@ -1403,11 +1399,11 @@ describe('MatMenu', () => {
const menus = overlay.querySelectorAll('.mat-menu-panel');

expect(menus[0].classList)
.toContain('mat-elevation-z2', 'Expected root menu to have base elevation.');
.toContain('mat-elevation-z4', 'Expected root menu to have base elevation.');
expect(menus[1].classList)
.toContain('mat-elevation-z3', 'Expected first sub-menu to have base elevation + 1.');
.toContain('mat-elevation-z5', 'Expected first sub-menu to have base elevation + 1.');
expect(menus[2].classList)
.toContain('mat-elevation-z4', 'Expected second sub-menu to have base elevation + 2.');
.toContain('mat-elevation-z6', 'Expected second sub-menu to have base elevation + 2.');
});

it('should update the elevation when the same menu is opened at a different depth',
Expand All @@ -1425,7 +1421,7 @@ describe('MatMenu', () => {
let lastMenu = overlay.querySelectorAll('.mat-menu-panel')[2];

expect(lastMenu.classList)
.toContain('mat-elevation-z4', 'Expected menu to have the base elevation plus two.');
.toContain('mat-elevation-z6', 'Expected menu to have the base elevation plus two.');

(overlay.querySelector('.cdk-overlay-backdrop')! as HTMLElement).click();
fixture.detectChanges();
Expand All @@ -1441,9 +1437,9 @@ describe('MatMenu', () => {
lastMenu = overlay.querySelector('.mat-menu-panel') as HTMLElement;

expect(lastMenu.classList)
.not.toContain('mat-elevation-z4', 'Expected menu not to maintain old elevation.');
.not.toContain('mat-elevation-z6', 'Expected menu not to maintain old elevation.');
expect(lastMenu.classList)
.toContain('mat-elevation-z2', 'Expected menu to have the proper updated elevation.');
.toContain('mat-elevation-z4', 'Expected menu to have the proper updated elevation.');
}));

it('should not increase the elevation if the user specified a custom one', () => {
Expand Down Expand Up @@ -1666,7 +1662,7 @@ describe('MatMenu default overrides', () => {
declarations: [SimpleMenu, FakeIcon],
providers: [{
provide: MAT_MENU_DEFAULT_OPTIONS,
useValue: {overlapTrigger: false, xPosition: 'before', yPosition: 'above'},
useValue: {overlapTrigger: true, xPosition: 'before', yPosition: 'above'},
}],
}).compileComponents();
}));
Expand All @@ -1676,7 +1672,7 @@ describe('MatMenu default overrides', () => {
fixture.detectChanges();
const menu = fixture.componentInstance.menu;

expect(menu.overlapTrigger).toBe(false);
expect(menu.overlapTrigger).toBe(true);
expect(menu.xPosition).toBe('before');
expect(menu.yPosition).toBe('above');
});
Expand Down