Skip to content
Snippets Groups Projects
menu-level-container.tsx 6.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • import {Component, Element, h, Host, Listen, Prop, State} from '@stencil/core';
    
    import {MenuType} from '../../../utils/utils';
    
    
    @Component({
      tag: 'hy-menu-level-container',
      styleUrl: 'menu-level-container.scss',
    
      shadow: false,
    
    })
    export class MenuLevelContainer {
      @Element() el: HTMLElement;
    
      @Prop() labelFrontPage?: string;
    
      @Prop() menuLevel: number;
      @Prop() menuType: MenuType = MenuType.mobile;
    
      @Prop({reflect: true}) activeTrailTriggered: boolean = false;
    
      @Prop({mutable: true, reflect: true}) depth: number = 0;
    
      @Prop({mutable: true, reflect: true}) triggerItem: string;
      @State() menuIsOpen: boolean = false;
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
      // 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');
          }
        });
      }
    
      // Listener for assigning active-trail for parent menu level container.
    
      @Listen('menuContainerActiveTrail', {target: 'document', capture: true})
      menuContainerActiveTrail(data) {
        const currentMenuContainer = this.el.getAttribute('trigger-item');
        if (currentMenuContainer === data.detail.triggerItem) {
          this.activeTrailTriggered = true;
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
          this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), 'add');
    
      // Listener for opening and closing menu level container.
    
      @Listen('menuContainerToggled', {target: 'document', capture: true})
      menuContainerToggled(data) {
        // Toggle submenu.
        if (this.triggerItem == data.detail.triggerItem) {
          this.activeTrailTriggered = false;
    
          this.menuIsOpen = data.detail.triggerType != 'remove';
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
          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;
    
      componentWillUpdate() {
    
        // Pass the menu type and menu-button-submenu-expand attributes to
        // the child menu item component.
    
        if (this.menuType) {
          const items = Array.from(this.el.children);
          items.forEach((item) => {
            item.setAttribute('menu-type', this.menuType);
    
            item.setAttribute('menu-button-submenu-expand', this.menuButtonSubmenuExpand);
    
        // Assign depth value to current menu level container instance;
        // 1st level, 2nd level, etc.
    
        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.
    
        if (this.menuType === 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'),
            };
    
            this.headingItem = {
              ...this.headingItem,
              isActive: window.location.pathname === this.headingItem.url,
            };
    
          } else {
            this.triggerItem = 'home';
          }
        }
    
        // Set is-active-child and menu-level attributes to all sibling menu-items.
    
        if (this.menuType === MenuType.sidenav) {
    
          const parentMenuItem = this.el.closest('hy-menu-item');
    
          if (parentMenuItem && parentMenuItem.classList.contains('is-active')) {
    
            const items = Array.from(this.el.children);
            items.forEach((item) => {
              item.setAttribute('is-active-child', 'true');
              item.setAttribute('menu-level', this.menuLevel.toString());
            });
          }
    
        }
      }
    
      render() {
        let classAttributes = ['hy-menu-level-container', 'hy-menu-level-container--level-' + this.depth];
    
    
        switch (this.menuType) {
    
            classAttributes = [...classAttributes, 'hy-menu-level-container--desktop'];
    
            //menu-type="sidenav"
    
              <Host class={classAttributes.join(' ')} menu-type="desktop">
    
            classAttributes = [...classAttributes, 'hy-menu-level-container--mobile'];
            if (this.depth === 1) {
              classAttributes = [...classAttributes, 'is-open'];
    
              return (
    
                <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
    
                  <slot />
                </Host>
              );
            } else {
    
              classAttributes = [...classAttributes, this.menuIsOpen ? 'is-open' : null];
    
                <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
    
                  <hy-menu-item
                    label={this.headingItem.label}
                    url={this.headingItem.url}
                    isHeading={true}
    
                    isActive={this.headingItem.isActive}
    
                    menu-type={'mobile'}
                  />
                  <slot />
                </Host>
              );
            }
    
            classAttributes = [...classAttributes, 'hy-menu-level-container--sidenav'];
    
    
            if (this.depth === 1) {
              classAttributes = [...classAttributes, 'is-open'];
    
              return (
    
                <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>
    
                  <slot />
                </Host>
              );
            } else {
    
              classAttributes = [...classAttributes, this.menuIsOpen ? 'is-open' : null];
    
                <Host aria-expanded={this.menuIsOpen.toString()} class={classAttributes.join(' ')} tabindex={'-1'}>