2.0 KiB
2.0 KiB
Dropdown Teleport Pattern
Problem
The #service-search-results dropdown lives inside #services-content, an accordion section with overflow: hidden. Even with z-index: 99999 !important, it's clipped by the parent stacking context and hidden behind the Quote Summary section.
Fix: Teleport to #dropdown-root
Every page has a <div id="dropdown-root"></div> at the end of <body>. When the dropdown opens, move it there and position it with position: fixed + getBoundingClientRect().
In renderServiceResults() (both main.js and quote-tab-manager.js):
// Teleport to dropdown-root to escape stacking context clipping
const dropdownRoot = document.getElementById('dropdown-root');
const serviceSearchInput = document.getElementById('service-search-input');
if (dropdownRoot && serviceSearchResults.parentElement !== dropdownRoot) {
dropdownRoot.appendChild(serviceSearchResults);
}
// Position relative to the input
if (serviceSearchInput) {
const rect = serviceSearchInput.getBoundingClientRect();
serviceSearchResults.style.position = 'fixed';
serviceSearchResults.style.top = (rect.bottom + 4) + 'px';
serviceSearchResults.style.left = rect.left + 'px';
serviceSearchResults.style.width = rect.width + 'px';
}
Scroll/resize repositioning (in initializeServiceSearch / attachMainEventListeners):
const repositionDropdown = () => {
if (serviceSearchResults.classList.contains('hidden')) return;
const rect = serviceSearchInput.getBoundingClientRect();
serviceSearchResults.style.top = (rect.bottom + 4) + 'px';
serviceSearchResults.style.left = rect.left + 'px';
serviceSearchResults.style.width = rect.width + 'px';
};
window.addEventListener('scroll', repositionDropdown, { passive: true });
window.addEventListener('resize', repositionDropdown);
Files Modified
main.js—renderServiceResults()+attachMainEventListeners()quote-tab-manager.js—renderServiceResults()+initializeServiceSearch()