Skip to content
Snippets Groups Projects
hy-desktop-menu-links.tsx 6.75 KiB
export interface DesktopLinks {
  label: string;
  url: string;
  menuLinkId: string;
  items: Array<DesktopLinks>;
}

import {ColorVariant} from '../../../utils/utils';
import {Component, h, Element, Listen, 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> = [];

  @Watch('dataDesktopLinks') dataDesktopLinksWatcher(data: DesktopLinks[] | string) {
    this._dataDesktopLinks = typeof data === 'string' ? JSON.parse(data) : data;
  }

  componentWillLoad() {
    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');
    });

    // 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');
      });
    }
  }

  @Listen('click')
  handleMenuDesktopLinkClick(event) {
    this.closeDesktopMenuPanel();
    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');
    });
    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');
    }
  }

  componentDidLoad() {
    const links = this._dataDesktopLinks as Array<DesktopLinks>;
    let firstLevelLinksList = [];

    links.forEach((item) => {
      let className = 'desktop-menu-link';
      firstLevelLinksList.push(
        <div
          class={className}
          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>
      );
    });

    this.firstLevelLinksList = firstLevelLinksList;
  }

  render() {
    return (
      <nav role={'navigation'} class="hy-site-header__menu-desktop">
        <ul>
          {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 (
                          <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>
                        );
                      })}
                  </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>
      </nav>
    );
  }
}