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() dataSiteHeaderLabels: 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} labels={this.searchLabels} /> <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} labels={this.languageLabels} /> <hy-site-search class={'menu--secondary__item'} size={14} color={black} show-label={true} labels={this.searchLabels} /> {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> ); } }