A menu groups choices in one place. In a share component, a Share button opens a menu of links for sharing a page by email or on social platforms. The button controls whether the links are shown; the menu holds the links themselves. section 11.2 section 11.6.2
Build the menu in small steps:
- Remove list-item bullets with `list-style: none`. Set the menu to `display: flex` to place its items in a row, and remove the browser’s default margin and padding. section 11.5.2
- Hide the closed menu with `width: 0` and `overflow: hidden`. When the container has the `share_expanded` class, give the menu a width and horizontal padding to expose the links. section 11.6.2
- Add `transition: width 250ms ease-in-out` so the menu expands and retracts when its width changes. section 11.6.3
A width transition does not solve every visibility problem: `overflow` switches between hidden and visible rather than changing gradually. If icons appear before the menu finishes opening, hide overflow immediately on closing and make it visible only after opening finishes. JavaScript transition events handle that timing; the supplied component also uses JavaScript for its button toggle and keyboard navigation. section 11.6.3 section 11.6.2 section 11.2
Closed and open styles
Start with `.share__menu { display: flex; margin: 0; padding: 0; width: 0; overflow: hidden; transition: width 250ms ease-in-out; }`. For the open state, use `.share_expanded .share__menu { width: 200px; padding: 0 2rem 0 1rem; }`. A button click toggles `share_expanded` on the component container. section 11.6.2 section 11.6.3
Listing 11.16 JavaScript for handling overflow
(() => {
'use strict';
let expanded = false;
const container = document.getElementById('share');
const menu = container.querySelector('menu');
...
addTransitionListeners();
...
function addTransitionListeners() {
menu.addEventListener('transitionstart', handleAnimationStart);
menu.addEventListener('transitionend', handleAnimationEnd);
}
...
function handleAnimationStart() { #1
if (!expanded) { menu.style.overflow = 'hidden'; } #2
}
...
function handleAnimationEnd() { #3
if (expanded) { menu.style.overflow = 'visible'; } #4
}
})()
The transition-event handlers show the precise workaround: hide overflow when closing starts and reveal it when opening ends. section 11.6.3
