Newer
Older
Markus Kalijärvi
committed
import {Component, Element, h, Host, Listen, Prop, State} from '@stencil/core';
@Component({
tag: 'hy-menu-level-container',
styleUrl: 'menu-level-container.scss',
Markus Kalijärvi
committed
})
export class MenuLevelContainer {
@Element() el: HTMLElement;
@State() open: boolean = false;
@Prop() menuLevel: number;
Markus Kalijärvi
committed
@Prop() menuButtonSubmenuExpand?: string;
Markus Kalijärvi
committed
@Prop({mutable: true, reflect: true}) triggerItem: string;
@Prop({mutable: true, reflect: true}) depth: number = 0;
@Prop({reflect: true}) activeTrailTriggered: boolean = false;
@Prop({mutable: true}) headingItem: any;
// Add/Remove is-hidden class from each upper level menu-items
// to make browsing more accessible.
assignMenuItemClass(parentMenu: Element, type: string) {
const items = Array.from(parentMenu.children);
items.forEach((item) => {
if (type === 'remove') {
item.classList.remove('is-hidden');
} else {
item.classList.add('is-hidden');
}
});
}
Markus Kalijärvi
committed
@Listen('menuContainerActiveTrail', {target: 'document', capture: true})
menuContainerActiveTrail(data) {
const currentMenuContainer = this.el.getAttribute('trigger-item');
if (currentMenuContainer === data.detail.triggerItem) {
this.activeTrailTriggered = true;
this.open = true;
this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), 'add');
Markus Kalijärvi
committed
}
}
@Listen('menuContainerToggled', {target: 'document', capture: true})
menuContainerToggled(data) {
// Toggle submenu.
if (this.triggerItem == data.detail.triggerItem) {
this.activeTrailTriggered = false;
this.open = data.detail.triggerType != 'remove';
this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), data.detail.triggerType);
// Scroll to .hy-menu top.
let hyMenu = this.el.parentElement.closest('hy-menu');
hyMenu.shadowRoot.querySelector('.hy-menu').scrollTop = 0;
Markus Kalijärvi
committed
}
}
componentWillUpdate() {
if (this.menuType) {
const items = Array.from(this.el.children);
items.forEach((item) => {
item.setAttribute('menu-type', this.menuType);
Markus Kalijärvi
committed
item.setAttribute('menu-button-submenu-expand', this.menuButtonSubmenuExpand);
Markus Kalijärvi
committed
componentWillRender() {
let parentMenu = this.el.closest('hy-menu-level-container');
let nextParentMenu;
this.depth = 0;
while (parentMenu) {
nextParentMenu = parentMenu.parentElement.closest('hy-menu-level-container');
if (nextParentMenu === parentMenu) {
break;
} else {
parentMenu = nextParentMenu;
this.depth = this.depth + 1;
}
}
// Set trigger item for each mobile menu level container and handle only submenus.
Markus Kalijärvi
committed
// Add a heading element foreach level.
if (this.menuType === 'mobile') {
if (this.menuLevel > 1) {
const parentMenuItem = this.el.closest('hy-menu-item');
this.triggerItem = parentMenuItem.getAttribute('menu-link-id');
this.headingItem = {
...this.headingItem,
url: parentMenuItem.getAttribute('url'),
};
this.headingItem = {
...this.headingItem,
label: parentMenuItem.getAttribute('label'),
};
} else {
this.triggerItem = 'home';
}
}
// Set is-active-child and menu-level attributes to all sibling menu-items.
if (this.menuType === 'sidenav') {
Markus Kalijärvi
committed
const parentMenuItem = this.el.closest('hy-menu-item');
if (parentMenuItem && parentMenuItem.classList.contains('is-active')) {
this.open = true;
const items = Array.from(this.el.children);
items.forEach((item) => {
item.setAttribute('is-active-child', 'true');
item.setAttribute('menu-level', this.menuLevel.toString());
});
}
Markus Kalijärvi
committed
}
}
render() {
let classAttributes = ['hy-menu-level-container', 'hy-menu-level-container--level-' + this.depth];
switch (this.menuType) {
case 'desktop':
classAttributes = [...classAttributes, 'hy-menu-level-container--desktop'];
<Host class={classAttributes.join(' ')}>
case 'mobile':
classAttributes = [...classAttributes, 'hy-menu-level-container--mobile'];
if (this.depth === 1) {
classAttributes = [...classAttributes, 'is-open'];
return (
<Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
<slot />
</Host>
);
} else {
classAttributes = [...classAttributes, this.open ? 'is-open' : null];
return (
<Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
<hy-menu-item
label={this.headingItem.label}
url={this.headingItem.url}
isHeading={true}
menu-type={'mobile'}
/>
<slot />
</Host>
);
}
case 'sidenav':
classAttributes = [...classAttributes, 'hy-menu-level-container--sidenav'];
if (this.depth === 1) {
classAttributes = [...classAttributes, 'is-open'];
return (
<Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
<slot />
</Host>
);
} else {
classAttributes = [...classAttributes, this.open ? 'is-open' : null];
return (
<Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
<slot />
</Host>
);
}