const hamburgerMenu = document.createElement('template') hamburgerMenu.innerHTML = `
` class HamburgerMenu extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }).append(hamburgerMenu.content.cloneNode(true)) this.resumeScrolling = this.resumeScrolling.bind(this) this.open = this.open.bind(this) this.close = this.close.bind(this) this.sideNav = this.shadowRoot.querySelector('.side-nav') this.backdrop = this.shadowRoot.querySelector('.backdrop') this.isOpen = false this.animeOptions = { duration: 300, easing: 'ease' } } static get observedAttributes() { return ['open']; } resumeScrolling() { const scrollY = document.body.style.top; window.scrollTo(0, parseInt(scrollY || '0') * -1); setTimeout(() => { document.body.style.overflow = 'auto'; document.body.style.top = 'initial' }, 300); } open() { if (this.isOpen) return document.body.style.overflow = 'hidden'; document.body.style.top = `-${window.scrollY}px` this.classList.remove('hide') this.sideNav.classList.add('reveal') this.backdrop.classList.remove('hide') this.backdrop.animate([ { opacity: 0 }, { opacity: 1 }, ], this.animeOptions) .onfinish = () => { this.isOpen = true this.setAttribute('open', '') } } close() { if (!this.isOpen) return this.sideNav.classList.remove('reveal') this.backdrop.animate([ { opacity: 1 }, { opacity: 0 }, ], this.animeOptions) .onfinish = () => { this.backdrop.classList.add('hide') this.classList.add('hide') this.isOpen = false this.removeAttribute('open') } } connectedCallback() { this.backdrop.addEventListener('click', this.close) const resizeObserver = new ResizeObserver(entries => { if (window.innerWidth < 640 && this.isOpen) { this.classList.remove('hide') } else { this.classList.add('hide') } if (window.innerWidth > 640) { this.classList.remove('hide') } }); resizeObserver.observe(this) } disconnectedCallback() { this.backdrop.removeEventListener('click', this.close) } attributeChangedCallback(name, oldVal, newVal) { if (name === 'open') { if (this.hasAttribute('open')) { this.open() } } } } window.customElements.define('hamburger-menu', HamburgerMenu);