Skip to content
Snippets Groups Projects
menu-level-container.tsx 3.25 KiB
Newer Older
  • Learn to ignore specific revisions
  • import {Component, Element, h, Host, Listen, Prop, State} from '@stencil/core';
    
    @Component({
      tag: 'hy-menu-level-container',
      styleUrl: 'menu-level-container.scss',
      shadow: false
    })
    export class MenuLevelContainer {
      @Element() el: HTMLElement;
    
      @State() open: boolean = false;
      @Prop() menuLevel: number;
      @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;
    
      @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;
        }
      }
    
      @Listen('menuContainerToggled', {target: 'document', capture: true})
      menuContainerToggled(data) {
        // Toggle submenu.
        if (this.triggerItem == data.detail.triggerItem) {
          this.activeTrailTriggered = false;
          this.open = !this.open;
    
          // Add/Remove is-hidden class from each upper level menu-items
          // to make browsing more accessible.
          let parentMenu = this.el.parentElement.closest('hy-menu-level-container');
          if (parentMenu) {
            const items = Array.from(parentMenu.children);
            items.forEach((item) => {
              if (data.detail.triggerType === 'remove') {
                item.classList.remove('is-hidden');
              } else {
                item.classList.add('is-hidden');
              }
            });
          }
        }
      }
    
      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 menu level container and handle only submenus.
        // Add a heading element foreach level.
        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';
        }
      }
    
      render() {
        let classAttributes = ['hy-menu-level-container', 'hy-menu-level-container--level-' + this.depth];
    
        if (this.depth === 1) {
          this.open = true;
          classAttributes = [...classAttributes, this.open ? 'is-open' : null];
    
          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} />
              <slot />
            </Host>
          );
        }
      }
    }