Something went wrong on our end
-
shamalainen authoredshamalainen authored
hy-desktop-menu-links.tsx 6.64 KiB
export interface ShortcutLinks {
shortcut_title: string;
shortcut_url: string;
shortcut_is_external: string;
shortcut_aria_label: string;
}
export interface DesktopLinks {
label: string;
url: string;
description: string;
menuLinkId: string;
isActive: string;
items: Array<DesktopLinks>;
shortcuts: Array<ShortcutLinks>;
}
import {ColorVariant} from '../../../utils/utils';
import {Component, h, Element, Prop, State, Watch} from '@stencil/core';
@Component({
tag: 'hy-desktop-menu-links',
styleUrl: 'hy-desktop-menu-links.scss',
shadow: true,
})
export class HyDesktopMenuLinks {
@Element() el: HTMLElement;
/*
First level menu links to be displayed on Desktop screens.
* */
@Prop() dataDesktopLinks: DesktopLinks[] | string;
private _dataDesktopLinks: DesktopLinks[];
@State() firstLevelLinksList: Array<object> = [];
@State() menuLinkItems: Array<object> = [];
@Watch('dataDesktopLinks') dataDesktopLinksWatcher(data: DesktopLinks[] | string) {
this._dataDesktopLinks = typeof data === 'string' ? JSON.parse(data) : data;
}
componentWillLoad() {
this.dataDesktopLinksWatcher(this.dataDesktopLinks);
}
handleDesktopMenuClose() {
const menuItems = this.el.shadowRoot.querySelectorAll(`.desktop-menu-link`);
const menuPanelItems = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel');
const activeMenuItem = this.el.shadowRoot.querySelector(`.desktop-menu-link[aria-expanded="true"]`);
// Return focus to the button of the last desktop panel that was active.
if (activeMenuItem !== null) (activeMenuItem as HTMLElement).focus();
// Reset elements by removing the active classes.
menuItems.forEach((item) => {
item.classList.remove('desktop-menu-link--is-active');
item.setAttribute('aria-expanded', 'false');
});
menuPanelItems.forEach((item) => {
item.classList.remove('hy-desktop-menu-panel--is-active');
item.setAttribute('aria-hidden', 'true');
});
}
handleDesktopMenuToggle(id) {
const menuItems = this.el.shadowRoot.querySelectorAll(`.desktop-menu-link`);
const menuPanelItems = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel');
const activeMenuItem = this.el.shadowRoot.querySelector(`.desktop-menu-link[link-id="${id}"]`);
const activeMenuItemSibling = activeMenuItem.nextElementSibling;
// Reset elements by removing the active classes.
menuItems.forEach((item) => {
item.classList.remove('desktop-menu-link--is-active');
item.setAttribute('aria-expanded', 'false');
});
menuPanelItems.forEach((item) => {
item.classList.remove('hy-desktop-menu-panel--is-active');
item.setAttribute('aria-hidden', 'true');
});
// Add active classes to the currently active item and its sibling element.
activeMenuItem.classList.add('desktop-menu-link--is-active');
activeMenuItem.setAttribute('aria-expanded', 'true');
activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active');
activeMenuItemSibling.setAttribute('aria-hidden', 'false');
}
componentDidLoad() {
const links = this._dataDesktopLinks as Array<DesktopLinks>;
let menuLinkItems = [];
links.map(({menuLinkId: id, shortcuts, items, url, description, label}) => {
menuLinkItems.push(
<li>
<button
type="button"
class="desktop-menu-link"
link-id={id}
onMouseOver={() => this.handleDesktopMenuToggle(id)}
onFocus={() => this.handleDesktopMenuToggle(id)}
aria-expanded="false"
>
{label}
<span class="desktop-menu-link__heading__icon">
<hy-icon icon={'hy-icon-caret-down'} size={16} />
</span>
</button>
<div class="hy-desktop-menu-panel" onMouseLeave={() => this.handleDesktopMenuClose()} aria-hidden="true">
<div class="hy-desktop-menu-panel__desktop-menu">
<a aria-current={label} href={url} class="" menu-link-id={id}>
<span class="heading-icon-first">
<hy-icon icon={'hy-icon-arrow-right'} size={40} />
</span>
<span class="hy-menu-item__label">{label}</span>
<span class="hy-menu-item__description">{description}</span>
</a>
<ul class={'desktop-menu first'} menu-link-id={id}>
{items.map(({label, url, description}) => (
<li>
<a href={url}>{label}</a>
<span>{description}</span>
</li>
))}
</ul>
{shortcuts.length > 0 && (
<ul class="shortcuts-panel">
<h2 class="shortcuts-panel__title">{'Shortcuts'}</h2>
{shortcuts.map(({shortcut_title, shortcut_url, shortcut_is_external, shortcut_aria_label}, index) => {
let target = shortcut_is_external ? '_blank' : '_self';
let shortcutClass = [
'shortcuts-panel__shortcut-item',
index == 0 ? 'shortcuts-panel__shortcut-item__first' : '',
].join(' ');
return (
<li class={shortcutClass}>
<a
aria-current={shortcut_aria_label}
href={shortcut_url}
class="shortcut-item__link"
target={target}
aria-label={shortcut_aria_label}
>
<span class="shortcut-item__label">{shortcut_title}</span>
<span class="shortcut-item__icon">
<hy-icon icon={'hy-icon-arrow-right'} size={24} />
</span>
</a>
</li>
);
})}
</ul>
)}
</div>
<button
onClick={() => this.handleDesktopMenuClose()}
class={{
'hy-desktop-menu-panel__panel-toggle': true,
}}
aria-label="Close menu"
>
<span class="hy-desktop-menu-panel__panel-toggle__label">
CLOSE
<hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
</span>
</button>
</div>
</li>
);
});
this.menuLinkItems = menuLinkItems;
}
render() {
return (
<nav role={'navigation'} class="hy-site-header__menu-desktop">
<ul class="hy-site-header__menu-desktop-container">{this.menuLinkItems}</ul>
</nav>
);
}
}