Skip to content
Snippets Groups Projects
site-header.tsx 5.28 KiB
Newer Older
  • Learn to ignore specific revisions
  • export interface DonateLink {
      url: string;
      label: string;
    }
    
    export interface ComponentLabels {
      open: string;
      close: string;
      expand?: string;
      label?: string;
    }
    
    
    import {Component, Element, Prop, State, h, Listen} from '@stencil/core';
    import ResizeObserver from 'resize-observer-polyfill';
    
    import {SiteLogoSize, SiteLogoColor} from '../../utils/utils';
    
    
    @Component({
      tag: 'hy-site-header',
      styleUrl: 'site-header.scss',
      shadow: true
    })
    export class SiteHeader {
      @Element() el: HTMLElement;
      @State() isMobile: boolean;
      @State() isMenuOpen: boolean = false;
      @Prop() dataMenuLanguage: string;
      @Prop() dataMenuDonate: string;
    
      @Prop() logoUrl?: string;
      @Prop() logoLabel?: string;
      @Prop({reflect: true}) menuType: string;
      private ro: ResizeObserver;
      private donateLink: DonateLink[];
    
      private menuLabels: ComponentLabels[];
      private searchLabels: ComponentLabels[];
      private languageLabels: ComponentLabels[];
    
    
      @Listen('mobileMenuToggle') mobileMenuToggle() {
        this.isMenuOpen = !this.isMenuOpen;
      }
    
      componentDidLoad() {
        this.ro = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.applySizeClasses(entry.contentRect.width);
          }
        });
    
        this.ro.observe(document.body);
    
        this.el.children[0].setAttribute('data-menu-language', this.dataMenuLanguage);
      }
    
      componentWillLoad() {
    
        const labels = JSON.parse(this.dataSiteHeaderLabels);
        this.menuLabels = labels.menu_labels;
        this.languageLabels = labels.language_labels;
        this.searchLabels = labels.search_labels;
    
        this.donateLink = JSON.parse(this.dataMenuDonate);
      }
    
      componentWillUpdate() {
        this.el.children[0].setAttribute('open', this.isMenuOpen.toString());
        this.el.children[0].setAttribute('logo-label', this.logoLabel);
        this.el.children[0].setAttribute('logo-url', this.logoUrl);
    
        this.el.children[0].setAttribute('menu-button-submenu-expand', this.menuLabels['expand']);
        this.el.children[0].setAttribute('menu-language-label-open', this.languageLabels['open']);
        this.el.children[0].setAttribute('menu-language-label-close', this.languageLabels['close']);
    
      }
    
      componentDidUnload() {
        this.ro.disconnect();
      }
    
      applySizeClasses(size: number) {
        if (size < 768) {
          this.el.children[0].setAttribute('menu-type', 'mobile');
          this.menuType = 'mobile';
          this.isMobile = true;
        } else {
          this.el.children[0].setAttribute('menu-type', 'desktop');
          this.menuType = 'desktop';
          this.isMobile = false;
        }
      }
    
      render() {
        const black = 'var(--brand-main-nearly-black)';
        const white = 'var(--grayscale-white)';
    
        const logoSize = this.isMobile ? SiteLogoSize.small : SiteLogoSize.big;
        const logoColor = this.isMobile ? SiteLogoColor.white : SiteLogoColor.black;
    
    
        let classAttributes = ['hy-site-header', 'hy-site-header--' + this.menuType];
        return this.isMobile ? (
          // Mobile
          <header class={classAttributes.join(' ')}>
            <div class={{'hy-backdrop': true, 'is-active': this.isMenuOpen}} />
    
            <div class={'hy-site-header__logo-container'}>
              <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
            </div>
    
            <div class={'hy-site-header__menu-container'}>
    
              <hy-site-search
                is-alternative={this.isMenuOpen}
                color={this.isMenuOpen ? black : white}
                size={20}
    
              <button
                onClick={() => this.mobileMenuToggle()}
                class={{
                  'hy-site-header__panel-toggle': true,
                  'is-open': this.isMenuOpen
                }}
    
                aria-label={this.isMenuOpen ? this.menuLabels['close'] : this.menuLabels['open']}
    
              >
                {this.isMenuOpen ? (
                  <hy-icon icon={'hy-icon-remove'} size={20} fill={black} />
                ) : (
                  <hy-icon icon={'hy-icon-hamburger'} size={20} fill={white} />
                )}
              </button>
              <div
                class={{
                  'is-open': this.isMenuOpen,
                  'hy-site-header__panel': true
                }}
              >
                <slot name={'menu'} />
              </div>
            </div>
          </header>
        ) : (
          // Desktop
          <header class={classAttributes.join(' ')}>
    
            <div class={'hy-site-header__logo-container'}>
              <hy-site-logo size={logoSize} color={logoColor} url={this.logoUrl} label={this.logoLabel} />
            </div>
    
            <slot name={'menu'} />
            <div class={'menu--secondary'}>
              <hy-menu-language
                class={'menu--secondary__item is-first'}
                is-mobile={false}
                data-menu-language={this.dataMenuLanguage}
    
              />
              <hy-site-search
                class={'menu--secondary__item'}
    
              />
              {this.donateLink.map((i) => {
                return (
                  <a class={'menu--secondary__item hy-link__donate'} href={i.url}>
                    <hy-icon icon={'hy-icon-euro'} size={14} fill={black} />
                    <span class={'hy-link__donate__label'}>{i.label}</span>
                  </a>
                );
              })}
            </div>
          </header>
        );
      }
    }