diff --git a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx index 41e9340b585f184a20ae1d6ec1686f9fc4eb8f9e..c1fd45358156c74c93b2a4609f4a65b01cb3729e 100644 --- a/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx +++ b/src/components/site-header/hy-desktop-menu-links/hy-desktop-menu-links.tsx @@ -31,6 +31,7 @@ export class HyDesktopMenuLinks { @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; @@ -40,176 +41,127 @@ export class HyDesktopMenuLinks { this.dataDesktopLinksWatcher(this.dataDesktopLinks); } - closeDesktopMenuPanel() { - // Remove is-active from desktop menu links. - let desktopMenuItems = this.el.shadowRoot.querySelectorAll('.desktop-menu-link'); - desktopMenuItems.forEach((item) => { - (item as HTMLElement).classList.remove('desktop-menu-link--is-active'); - }); + handleDesktopMenuClose() { + const menuItems = this.el.shadowRoot.querySelectorAll(`.desktop-menu-link`); + const menuPanelItems = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel'); - // Close desktop menu panel. - let hyDesktopPanel = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel')[0]; - if (hyDesktopPanel) { - // Hide panel, remove class is-active. - (hyDesktopPanel as HTMLElement).classList.remove('hy-desktop-menu-panel--is-active'); - - let menuItems = hyDesktopPanel.querySelectorAll('ul.first'); - menuItems.forEach((item) => { - (item as HTMLElement).classList.remove('desktop-menu--is-active'); - }); - } + // Reset elements by removing the active classes. + menuItems.forEach((item) => { + item.classList.remove('desktop-menu-link--is-active'); + }); + menuPanelItems.forEach((item) => { + item.classList.remove('hy-desktop-menu-panel--is-active'); + }); } @Listen('click') handleMenuDesktopLinkClick(event) { - this.closeDesktopMenuPanel(); + this.handleDesktopMenuClose(); event.stopPropagation(); } - //Show desktop menu panel - handleMenuDesktopHover(id) { - // Set is-active class for the desktop menu selected link to highlight it. - let desktopMenuItems = this.el.shadowRoot.querySelectorAll('.desktop-menu-link'); - desktopMenuItems.forEach((item) => { - (item as HTMLElement).classList.remove('desktop-menu-link--is-active'); + 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'); }); - let desktopMenuActivatedItems = this.el.shadowRoot.querySelectorAll('.desktop-menu-link[link-id="' + id + '"]'); - (desktopMenuActivatedItems[0] as HTMLElement).classList.add('desktop-menu-link--is-active'); - - let hyDesktopPanel = this.el.shadowRoot.querySelectorAll('.hy-desktop-menu-panel')[0]; - if (hyDesktopPanel) { - // Show panel, add class is-active. - (hyDesktopPanel as HTMLElement).classList.add('hy-desktop-menu-panel--is-active'); - - // Show proper subtree on panel based on given menu-link-id. - let menuItems = hyDesktopPanel.querySelectorAll('ul.first'); - menuItems.forEach((item) => { - (item as HTMLElement).classList.remove('desktop-menu--is-active'); - }); - - let menuActivatedItems = hyDesktopPanel.querySelectorAll('ul[menu-link-id="' + id + '"]'); - (menuActivatedItems[0] as HTMLElement).classList.add('desktop-menu--is-active'); - } + menuPanelItems.forEach((item) => { + item.classList.remove('hy-desktop-menu-panel--is-active'); + }); + + // Add active classes to the currently active item and its sibling element. + activeMenuItem.classList.add('desktop-menu-link--is-active'); + activeMenuItemSibling.classList.add('hy-desktop-menu-panel--is-active'); } componentDidLoad() { const links = this._dataDesktopLinks as Array<DesktopLinks>; - let firstLevelLinksList = []; - - links.forEach((item) => { - let classAttributes = [ - 'desktop-menu-link', - item.isActive === 'true' ? 'desktop-menu-link--is-active-trail' : '', - ].join(' '); - - //item.isActive ? classAttributes'desktop-menu-link--is-active-trail' : '' - - firstLevelLinksList.push( - <div - class={classAttributes} - link-id={item.menuLinkId} - onMouseOver={() => this.handleMenuDesktopHover(item.menuLinkId)} - onFocus={() => this.handleMenuDesktopHover(item.menuLinkId)} - tabIndex={0} - > - {item.label} - <span class="desktop-menu-link__heading__icon"> - <hy-icon icon={'hy-icon-caret-down'} size={16} /> - </span> - </div> + + 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)} + > + {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()}> + <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"> + {shortcuts.map(({shortcut_title, shortcut_url, shortcut_is_external, shortcut_aria_label}) => { + let target = shortcut_is_external ? '_blank' : '_self'; + + return ( + <li class="shortcut-item"> + <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> + </a> + </li> + ); + })} + </ul> + )} + </div> + <button + onClick={() => this.handleDesktopMenuClose()} + class={{ + 'hy-desktop-menu-panel__panel-toggle': true, + }} + aria-label="close" + > + <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.firstLevelLinksList = firstLevelLinksList; + this.menuLinkItems = menuLinkItems; } render() { return ( <nav role={'navigation'} class="hy-site-header__menu-desktop"> - <ul class="hy-site-header__menu-desktop-container"> - {this.firstLevelLinksList.map((firstLevelLink) => { - return ( - <li> - {firstLevelLink} - <div class="hy-desktop-menu-panel" onMouseLeave={() => this.closeDesktopMenuPanel()}> - <div class="hy-desktop-menu-panel__desktop-menu"> - {this._dataDesktopLinks && - this._dataDesktopLinks.map((link) => { - return ( - <div> - <ul class={'desktop-menu first'} menu-link-id={link.menuLinkId}> - <li class={'first'}> - <a aria-current={link.label} href={link.url} class="" menu-link-id={link.menuLinkId}> - <span class="heading-icon-first"> - <hy-icon icon={'hy-icon-arrow-right'} size={40} /> - </span> - <span class="hy-menu-item__label">{link.label}</span> - </a> - {link.items && ( - <ul class="second" menu-link-id={link.menuLinkId}> - {link.items.map((subitem) => { - return ( - <li class={'second'}> - <a - aria-current={subitem.label} - href={subitem.url} - class="" - menu-link-id={subitem.menuLinkId} - > - <span class="heading-icon-second"> - <hy-icon icon={'hy-icon-caret-right'} size={12} /> - </span> - <span class="hy-menu-item__label">{subitem.label}</span> - </a> - </li> - ); - })} - </ul> - )} - </li> - </ul> - {link.shortcuts.length > 0 && ( - <div class="shortcuts-panel"> - <span class="shortcut-panel__title">{'Shortcuts'}</span> - {link.shortcuts.map((shortcut_item) => { - let target = shortcut_item.shortcut_is_external ? '_blank' : '_self'; - return ( - <div class="shortcut-item"> - <a - aria-current={shortcut_item.shortcut_aria_label} - href={shortcut_item.shortcut_url} - class="shortcut-item__link" - target={target} - aria-label={shortcut_item.shortcut_aria_label} - > - <span class="shortcut-item__label">{shortcut_item.shortcut_title}</span> - </a> - </div> - ); - })} - </div> - )} - </div> - ); - })} - </div> - <button - onClick={() => this.closeDesktopMenuPanel()} - class={{ - 'hy-desktop-menu-panel__panel-toggle': true, - }} - aria-label="close" - > - <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> - ); - })} - </ul> + <ul class="hy-site-header__menu-desktop-container">{this.menuLinkItems}</ul> </nav> ); }