Skip to content

Commit

Permalink
feat(menu): add indicator to menu items that trigger a sub-menu (#5995)
Browse files Browse the repository at this point in the history
Adds an arrow indicator to the `md-menu-item` instances that trigger a sub-menu.
  • Loading branch information
crisbeto authored and andrewseguin committed Jul 27, 2017
1 parent eaa6099 commit a51f82f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
9 changes: 4 additions & 5 deletions src/lib/menu/_menu-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
&[disabled] {
color: mat-color($foreground, 'disabled');
}
}

.mat-icon {
color: mat-color($foreground, 'icon');
vertical-align: middle;
}

.mat-menu-item .mat-icon,
.mat-menu-item-submenu-trigger::after {
color: mat-color($foreground, 'icon');
}

.mat-menu-item:hover,
Expand Down
4 changes: 4 additions & 0 deletions src/lib/menu/menu-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const _MdMenuItemMixinBase = mixinDisabled(MdMenuItemBase);
'role': 'menuitem',
'class': 'mat-menu-item',
'[class.mat-menu-item-highlighted]': '_highlighted',
'[class.mat-menu-item-submenu-trigger]': '_triggersSubmenu',
'[attr.tabindex]': '_getTabIndex()',
'[attr.aria-disabled]': 'disabled.toString()',
'[attr.disabled]': 'disabled || null',
Expand All @@ -45,6 +46,9 @@ export class MdMenuItem extends _MdMenuItemMixinBase implements Focusable, CanDi
/** Whether the menu item is highlighted. */
_highlighted: boolean = false;

/** Whether the menu item acts as a trigger for a sub-menu. */
_triggersSubmenu: boolean = false;

constructor(private _elementRef: ElementRef) {
super();
}
Expand Down
20 changes: 13 additions & 7 deletions src/lib/menu/menu-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,19 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
/** Event emitted when the associated menu is closed. */
@Output() onMenuClose = new EventEmitter<void>();

constructor(private _overlay: Overlay,
private _element: ElementRef,
private _viewContainerRef: ViewContainerRef,
@Inject(MD_MENU_SCROLL_STRATEGY) private _scrollStrategy,
@Optional() private _parentMenu: MdMenu,
@Optional() @Self() private _menuItemInstance: MdMenuItem,
@Optional() private _dir: Directionality) { }
constructor(
private _overlay: Overlay,
private _element: ElementRef,
private _viewContainerRef: ViewContainerRef,
@Inject(MD_MENU_SCROLL_STRATEGY) private _scrollStrategy,
@Optional() private _parentMenu: MdMenu,
@Optional() @Self() private _menuItemInstance: MdMenuItem,
@Optional() private _dir: Directionality) {

if (_menuItemInstance) {
_menuItemInstance._triggersSubmenu = this.triggersSubmenu();
}
}

ngAfterViewInit() {
this._checkMenu();
Expand Down
39 changes: 38 additions & 1 deletion src/lib/menu/menu.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// TODO(kara): update vars for desktop when MD team responds
// TODO(kara): animation for menu opening

@import '../core/style/button-common';
@import '../core/style/layout-common';
Expand All @@ -8,6 +7,7 @@

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

.mat-menu-panel {
@include mat-menu-base(2);
Expand Down Expand Up @@ -36,6 +36,43 @@ $mat-menu-border-radius: 2px !default;
@include mat-button-reset();
@include mat-menu-item-base();
position: relative;

.mat-icon {
vertical-align: middle;
}
}

.mat-menu-item-submenu-trigger {
// Increase the side padding to prevent the indicator from overlapping the text.
padding-right: $mat-menu-side-padding * 2;

// Renders a triangle to indicate that the menu item will open a sub-menu.
&::after {
$size: $mat-menu-submenu-indicator-size / 2;

width: 0;
height: 0;
border-style: solid;
border-width: $size 0 $size $size;
border-color: transparent transparent transparent currentColor;
content: '';
display: inline-block;
position: absolute;
top: 50%;
right: $mat-menu-side-padding;
transform: translateY(-50%);
}

[dir='rtl'] & {
padding-right: $mat-menu-side-padding / 2;
padding-left: $mat-menu-side-padding * 2;

&::after {
right: auto;
left: $mat-menu-side-padding;
transform: rotateY(180deg) translateY(-50%);
}
}
}

button.mat-menu-item {
Expand Down
11 changes: 11 additions & 0 deletions src/lib/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,17 @@ describe('MdMenu', () => {
expect(overlay.querySelectorAll('.mat-menu-panel').length).toBe(0, 'Expected no open menus');
});

it('should set a class on the menu items that trigger a sub-menu', () => {
compileTestComponent();
instance.rootTrigger.openMenu();
fixture.detectChanges();

const menuItems = overlay.querySelectorAll('[md-menu-item]');

expect(menuItems[0].classList).toContain('mat-menu-item-submenu-trigger');
expect(menuItems[1].classList).not.toContain('mat-menu-item-submenu-trigger');
});

});

});
Expand Down

0 comments on commit a51f82f

Please sign in to comment.