basecoat-css
Version:
Tailwind CSS for Basecoat components
74 lines (62 loc) • 2.23 kB
JavaScript
(() => {
const initPopover = (popoverComponent) => {
const trigger = popoverComponent.querySelector(':scope > button');
const content = popoverComponent.querySelector(':scope > [data-popover]');
if (!trigger || !content) {
const missing = [];
if (!trigger) missing.push('trigger');
if (!content) missing.push('content');
console.error(`Popover initialisation failed. Missing element(s): ${missing.join(', ')}`, popoverComponent);
return;
}
const closePopover = (focusOnTrigger = true) => {
if (trigger.getAttribute('aria-expanded') === 'false') return;
trigger.setAttribute('aria-expanded', 'false');
content.setAttribute('aria-hidden', 'true');
if (focusOnTrigger) {
trigger.focus();
}
};
const openPopover = () => {
document.dispatchEvent(new CustomEvent('basecoat:popover', {
detail: { source: popoverComponent }
}));
const elementToFocus = content.querySelector('[autofocus]');
if (elementToFocus) {
content.addEventListener('transitionend', () => {
elementToFocus.focus();
}, { once: true });
}
trigger.setAttribute('aria-expanded', 'true');
content.setAttribute('aria-hidden', 'false');
};
trigger.addEventListener('click', () => {
const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
if (isExpanded) {
closePopover();
} else {
openPopover();
}
});
popoverComponent.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closePopover();
}
});
document.addEventListener('click', (event) => {
if (!popoverComponent.contains(event.target)) {
closePopover();
}
});
document.addEventListener('basecoat:popover', (event) => {
if (event.detail.source !== popoverComponent) {
closePopover(false);
}
});
popoverComponent.dataset.popoverInitialized = true;
popoverComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
};
if (window.basecoat) {
window.basecoat.register('popover', '.popover:not([data-popover-initialized])', initPopover);
}
})();