mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-14 22:18:19 +00:00
Fixing more issues with popovers
This commit is contained in:
+31
-18
@@ -16,19 +16,30 @@
|
||||
let menuItems = [];
|
||||
let activeIndex = -1;
|
||||
|
||||
const closeMenu = () => {
|
||||
const closePopover = (focusOnTrigger = true) => {
|
||||
if (trigger.getAttribute('aria-expanded') === 'false') return;
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
trigger.removeAttribute('aria-activedescendant');
|
||||
popover.setAttribute('aria-hidden', 'true');
|
||||
trigger.focus();
|
||||
|
||||
if (focusOnTrigger) {
|
||||
trigger.focus();
|
||||
}
|
||||
|
||||
setActiveItem(-1);
|
||||
};
|
||||
|
||||
const openMenu = () => {
|
||||
const openPopover = () => {
|
||||
document.dispatchEvent(new CustomEvent('basecoat:popover', {
|
||||
detail: { source: dropdownMenuComponent }
|
||||
}));
|
||||
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
popover.setAttribute('aria-hidden', 'false');
|
||||
menuItems = Array.from(menu.querySelectorAll('[role^="menuitem"]:not([disabled])'));
|
||||
menuItems = Array.from(menu.querySelectorAll('[role^="menuitem"]')).filter(item =>
|
||||
!item.hasAttribute('disabled') &&
|
||||
item.getAttribute('aria-disabled') !== 'true'
|
||||
);
|
||||
if (menuItems.length > 0) {
|
||||
setActiveItem(0);
|
||||
}
|
||||
@@ -51,9 +62,9 @@
|
||||
trigger.addEventListener('click', () => {
|
||||
const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
|
||||
if (isExpanded) {
|
||||
closeMenu();
|
||||
closePopover();
|
||||
} else {
|
||||
openMenu();
|
||||
openPopover();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -61,14 +72,14 @@
|
||||
const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
if (isExpanded) closeMenu();
|
||||
if (isExpanded) closePopover();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isExpanded) {
|
||||
if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) {
|
||||
event.preventDefault();
|
||||
openMenu();
|
||||
openPopover();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -80,15 +91,11 @@
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (activeIndex < menuItems.length - 1) {
|
||||
nextIndex = activeIndex + 1;
|
||||
}
|
||||
break;
|
||||
nextIndex = Math.min(activeIndex + 1, menuItems.length - 1);
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
event.preventDefault();
|
||||
if (activeIndex > 0) {
|
||||
nextIndex = activeIndex - 1;
|
||||
}
|
||||
nextIndex = Math.max(activeIndex - 1, 0);
|
||||
break;
|
||||
case 'Home':
|
||||
event.preventDefault();
|
||||
@@ -102,7 +109,7 @@
|
||||
case ' ':
|
||||
event.preventDefault();
|
||||
menuItems[activeIndex]?.click();
|
||||
closeMenu();
|
||||
closePopover();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -113,13 +120,19 @@
|
||||
|
||||
menu.addEventListener('click', (event) => {
|
||||
if (event.target.closest('[role^="menuitem"]')) {
|
||||
closeMenu();
|
||||
closePopover();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', (event) => {
|
||||
if (!dropdownMenuComponent.contains(event.target)) {
|
||||
closeMenu();
|
||||
closePopover();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('basecoat:popover', (event) => {
|
||||
if (event.detail.source !== dropdownMenuComponent) {
|
||||
closePopover(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+14
-2
@@ -11,14 +11,20 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const closePopover = () => {
|
||||
const closePopover = (focusOnTrigger = true) => {
|
||||
if (trigger.getAttribute('aria-expanded') === 'false') return;
|
||||
trigger.setAttribute('aria-expanded', 'false');
|
||||
content.setAttribute('aria-hidden', 'true');
|
||||
trigger.focus();
|
||||
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', () => {
|
||||
@@ -51,6 +57,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('basecoat:popover', (event) => {
|
||||
if (event.detail.source !== popoverComponent) {
|
||||
closePopover(false);
|
||||
}
|
||||
});
|
||||
|
||||
popoverComponent.dataset.popoverInitialized = true;
|
||||
};
|
||||
|
||||
|
||||
+40
-27
@@ -148,7 +148,7 @@
|
||||
if (currentVisibleIndex > 0) {
|
||||
nextVisibleIndex = currentVisibleIndex - 1;
|
||||
} else if (currentVisibleIndex === -1) {
|
||||
nextVisibleIndex = 0; // Start from top if nothing is active
|
||||
nextVisibleIndex = 0;
|
||||
}
|
||||
break;
|
||||
case 'Home':
|
||||
@@ -180,37 +180,44 @@
|
||||
filter.addEventListener('keydown', handleKeyNavigation);
|
||||
}
|
||||
|
||||
const openPopover = () => {
|
||||
document.dispatchEvent(new CustomEvent('basecoat:popover', {
|
||||
detail: { source: selectComponent }
|
||||
}));
|
||||
|
||||
if (filter) {
|
||||
if (hasTransition()) {
|
||||
popover.addEventListener('transitionend', () => {
|
||||
filter.focus();
|
||||
}, { once: true });
|
||||
} else {
|
||||
filter.focus();
|
||||
}
|
||||
}
|
||||
|
||||
popover.setAttribute('aria-hidden', 'false');
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
|
||||
const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
|
||||
if (selectedOption) {
|
||||
if (activeIndex > -1) {
|
||||
options[activeIndex]?.classList.remove('active');
|
||||
}
|
||||
activeIndex = options.indexOf(selectedOption);
|
||||
selectedOption.classList.add('active');
|
||||
if (selectedOption.id) {
|
||||
trigger.setAttribute('aria-activedescendant', selectedOption.id);
|
||||
}
|
||||
selectedOption.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
};
|
||||
|
||||
trigger.addEventListener('click', () => {
|
||||
const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
|
||||
|
||||
if (isExpanded) {
|
||||
closePopover();
|
||||
} else {
|
||||
if (filter) {
|
||||
if (hasTransition()) {
|
||||
popover.addEventListener('transitionend', () => {
|
||||
filter.focus();
|
||||
}, { once: true });
|
||||
} else {
|
||||
filter.focus();
|
||||
}
|
||||
}
|
||||
|
||||
popover.setAttribute('aria-hidden', 'false');
|
||||
trigger.setAttribute('aria-expanded', 'true');
|
||||
|
||||
const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
|
||||
if (selectedOption) {
|
||||
if (activeIndex > -1) {
|
||||
options[activeIndex]?.classList.remove('active');
|
||||
}
|
||||
activeIndex = options.indexOf(selectedOption);
|
||||
selectedOption.classList.add('active');
|
||||
if (selectedOption.id) {
|
||||
trigger.setAttribute('aria-activedescendant', selectedOption.id);
|
||||
}
|
||||
selectedOption.scrollIntoView({ block: 'nearest' });
|
||||
}
|
||||
openPopover();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -227,6 +234,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('basecoat:popover', (event) => {
|
||||
if (event.detail.source !== selectComponent) {
|
||||
closePopover(false);
|
||||
}
|
||||
});
|
||||
|
||||
popover.setAttribute('aria-hidden', 'true');
|
||||
selectComponent.dataset.selectInitialized = true;
|
||||
};
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@
|
||||
const initialToaster = document.getElementById('toaster');
|
||||
if (initialToaster) initToaster(initialToaster);
|
||||
|
||||
window.addEventListener('basecoat:toast', (event) => {
|
||||
document.addEventListener('basecoat:toast', (event) => {
|
||||
if (!toaster) {
|
||||
console.error('Cannot create toast: toaster container not found on page.');
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user