I am focusing on the mobile portion of a menu, basically mimicking a bootstrap menu I already have in place.
Brains are a bit frazzled at the moment, so not sure if I am missing a trick or two. I have done a few of these over the years, but don’t remember having to take into account transitions and reflows.
Any feedback or decent resources would be appreciated.
const getElem = document.querySelector.bind(document)
const propChange = (elem, prop, value) => {
// override transition
elem.classList.add('removeTransition')
// assign property
window.requestAnimationFrame(() => (elem.style[prop] = value))
// force reflow
window.getComputedStyle(elem).opacity
// reassign transition
elem.classList.remove('removeTransition')
}
const expanded = event => {
const elem = event.currentTarget
elem.removeEventListener('transitionend', expanded, false)
// Set to 'auto'. Container needs to be able to expand with nested menu
elem.style.height = 'auto'
elem.dataset.collapsed = 'false'
}
const expand = elem => {
elem.style.height = `${elem.scrollHeight}px`
elem.addEventListener('transitionend', expanded, false)
}
const collapsed = event => {
const elem = event.currentTarget
elem.removeEventListener('transitionend', collapsed, false)
elem.dataset.collapsed = 'true'
}
const collapse = elem => {
// need expanded height first
elem.style.height = `${elem.scrollHeight}px`
propChange(elem, 'height', '0px')
elem.addEventListener('transitionend', collapsed, false)
}
document.addEventListener('DOMContentLoaded', event => {
const menuButton = getElem('#menubutton')
const dropdownButton = getElem('#dropdown button')
const menu = getElem('#menu')
menuButton.addEventListener('click', event => (
menu.dataset.collapsed === 'true' ? expand(menu) : collapse(menu)
))
dropdownButton.addEventListener('click', event => {
const dropdown = event.currentTarget.parentElement
dropdown.classList.toggle('open')
})
})
Codepen here
Thanks