Skip to content
Snippets Groups Projects
menu-level-container.tsx 4.15 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() menuType?: string;
    
      @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;
    
    
    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');
          }
        });
      }
    
    
      @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;
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
          this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), 'add');
    
        }
      }
    
      @Listen('menuContainerToggled', {target: 'document', capture: true})
      menuContainerToggled(data) {
        // Toggle submenu.
        if (this.triggerItem == data.detail.triggerItem) {
          this.activeTrailTriggered = false;
          this.open = !this.open;
    
    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() {
        if (this.menuType) {
          const items = Array.from(this.el.children);
          items.forEach((item) => {
            item.setAttribute('menu-type', this.menuType);
          });
        }
      }
    
    
      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.menuType === 'desktop') {
          classAttributes = [...classAttributes, 'hy-menu--desktop'];
    
            <Host class={classAttributes.join(' ')}>
    
          classAttributes = [...classAttributes, 'hy-menu--mobile'];
    
          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}
                  menu-type={'mobile'}
                />