diff --git a/assets/css/frontend/nav/header-menu-buttons.css b/assets/css/frontend/nav/header-menu-buttons.css index 3270dcd0..b6d41042 100644 --- a/assets/css/frontend/nav/header-menu-buttons.css +++ b/assets/css/frontend/nav/header-menu-buttons.css @@ -52,8 +52,9 @@ box-sizing: border-box; vertical-align: middle; flex: 0 0 auto !important; - width: auto !important; - max-width: none !important; + /* fit-content: chip hugs label; never stretch to parent/menu */ + width: fit-content !important; + max-width: fit-content !important; min-width: 0 !important; margin: 0 !important; appearance: none; @@ -98,10 +99,9 @@ .navbar-but-cluster .navbar-vip { position: relative; overflow: visible !important; - display: inline-flex !important; - align-items: center; - width: auto !important; - max-width: none !important; + display: block !important; + width: fit-content !important; + max-width: fit-content !important; min-width: 0 !important; flex: 0 0 auto !important; height: 34px; @@ -124,45 +124,51 @@ /* * Publish multi-type dropdown - * inline-grid with one max-content column sized ONLY by the in-flow toggle. - * Absolute dropdown is out of track sizing so open cannot widen the chip. + * + * The pink chip must NEVER share layout with the 168px menu. + * - wrapper = content-sized box (width: fit-content, no stretch) + * - toggle = only painted control + * - menu = absolute under wrapper, does not affect chip width */ +.navbar-but-cluster .navbar-but { + /* outer shell around publish */ + display: block !important; + width: fit-content !important; + max-width: fit-content !important; + min-width: 0 !important; + height: 34px !important; + flex: 0 0 auto !important; + position: relative; + overflow: visible !important; +} + .navbar-but-cluster .navbar-but .newadd-btns.hover-show, .navbar-but-cluster .newadd-btns.hover-show, .newadd-btns.hover-show { position: relative !important; - display: inline-grid !important; - grid-template-columns: max-content; - grid-template-rows: 34px; - justify-items: stretch; - align-items: center; - vertical-align: middle; - z-index: 40; - background: transparent !important; - color: inherit !important; - padding: 0 !important; - margin: 0 !important; - border: 0 !important; - box-shadow: none !important; - width: auto !important; - max-width: none !important; + display: block !important; + width: fit-content !important; + max-width: fit-content !important; min-width: 0 !important; height: 34px !important; max-height: 34px !important; - line-height: 0 !important; + padding: 0 !important; + margin: 0 !important; + border: 0 !important; + background: transparent !important; + box-shadow: none !important; overflow: visible !important; - flex: 0 0 auto !important; - align-self: center; - white-space: nowrap; + z-index: 40; + line-height: 0 !important; float: none !important; + flex: 0 0 auto !important; } +/* Pink chip only — content width, never 100% of anything */ .navbar-but-cluster .newadd-btns > .newadd-btns__toggle, .navbar-but-cluster button.newadd-btns__toggle, .navbar-but-cluster a.newadd-btns__toggle, .navbar-but-cluster .newadd-btns__toggle.navbar-cta { - grid-column: 1; - grid-row: 1; display: inline-flex !important; align-items: center !important; justify-content: center !important; @@ -172,37 +178,41 @@ max-height: 34px !important; padding: 0 14px !important; margin: 0 !important; - width: auto !important; - max-width: none !important; + width: fit-content !important; + max-width: fit-content !important; min-width: 0 !important; box-sizing: border-box !important; white-space: nowrap !important; position: relative; z-index: 2; - justify-self: start; + flex: 0 0 auto !important; } +/* Hard-lock open/focus: still content-sized, never stretch */ +.navbar-but-cluster .newadd-btns > .newadd-btns__toggle:hover, .navbar-but-cluster .newadd-btns > .newadd-btns__toggle:focus, .navbar-but-cluster .newadd-btns > .newadd-btns__toggle:focus-visible, .navbar-but-cluster .newadd-btns > .newadd-btns__toggle:active, .navbar-but-cluster .newadd-btns.hover-show:hover > .newadd-btns__toggle, .navbar-but-cluster .newadd-btns.hover-show:focus-within > .newadd-btns__toggle { - width: auto !important; + width: fit-content !important; + max-width: fit-content !important; + min-width: 0 !important; padding: 0 14px !important; height: 34px !important; transform: none !important; - opacity: 1; + flex: 0 0 auto !important; } +/* Menu floats under chip; fixed width; cannot expand chip */ .navbar-but-cluster .newadd-btns > .drop-newadd, .navbar-but-cluster .newadd-btns .hover-show-con.drop-newadd, .newadd-btns > .drop-newadd, .newadd-btns .hover-show-con.drop-newadd { - grid-column: 1; - grid-row: 1; display: block !important; position: absolute !important; - top: 100% !important; + top: calc(100% + 0px) !important; + /* Align menu to the RIGHT edge of the chip, not stretch chip */ right: 0 !important; left: auto !important; bottom: auto !important; @@ -223,7 +233,6 @@ z-index: 1200 !important; pointer-events: none; box-sizing: border-box !important; - justify-self: end; } .navbar-but-cluster .newadd-btns .drop-newadd::before, @@ -325,6 +334,83 @@ body.theme-dark .newadd-btns__item:hover { background: rgba(255, 255, 255, 0.06) !important; } + +/* Portaled publish menu (moved to body by header-newadd.js) */ +.newadd-btns.is-js-portal:hover > .drop-newadd, +.newadd-btns.is-js-portal:focus-within > .drop-newadd, +.newadd-btns.is-js-portal > .drop-newadd { + /* never paint/show menu while still inside chip wrapper */ + opacity: 0 !important; + visibility: hidden !important; + pointer-events: none !important; + display: none !important; +} + +body > .drop-newadd.hover-show-con, +body > .drop-newadd { + display: none; + position: fixed; + z-index: 2000; + width: 168px; + min-width: 168px; + max-width: 168px; + margin: 0; + padding: 6px 0; + background: #ffffff !important; + color: #222222 !important; + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + box-sizing: border-box; +} + +body > .drop-newadd.is-open { + display: block !important; + opacity: 1 !important; + visibility: visible !important; + pointer-events: auto !important; + transform: none !important; +} + +body > .drop-newadd::before { + content: none !important; + display: none !important; +} + +body > .drop-newadd .newadd-btns__item { + display: flex !important; + align-items: center; + gap: 8px; + padding: 8px 14px !important; + color: #222222 !important; + text-decoration: none !important; + font-size: 13px !important; + font-weight: 500; + background: transparent !important; + width: 100% !important; + height: auto !important; + box-sizing: border-box; +} + +body > .drop-newadd .newadd-btns__item:hover { + background: rgba(0, 0, 0, 0.05) !important; + color: var(--color-primary, #f04494) !important; +} + +html.dark body > .drop-newadd, +body.dark-theme body > .drop-newadd, +body.theme-dark body > .drop-newadd { + background: #323335 !important; + color: #f1f5f9 !important; + border-color: rgba(255, 255, 255, 0.08); +} + +html.dark body > .drop-newadd .newadd-btns__item, +body.dark-theme body > .drop-newadd .newadd-btns__item, +body.theme-dark body > .drop-newadd .newadd-btns__item { + color: #f1f5f9 !important; +} + /* Generic hover-show (zibll parity) */ .hover-show { position: relative; diff --git a/assets/js/header-newadd.js b/assets/js/header-newadd.js new file mode 100644 index 00000000..8ef329c0 --- /dev/null +++ b/assets/js/header-newadd.js @@ -0,0 +1,167 @@ +/** + * Header multi-type publish menu: portal dropdown to document.body. + * + * Keeps the pink chip content-sized. The menu is position:fixed under the + * toggle and never participates in the chip's layout width. + * + * @package AKSRT + */ +(function () { + 'use strict'; + + var openRoot = null; + var openMenu = null; + var openToggle = null; + var closeTimer = null; + + function clearCloseTimer() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = null; + } + } + + function placeMenu(toggle, menu) { + var rect = toggle.getBoundingClientRect(); + var menuWidth = 168; + var left = rect.right - menuWidth; + if (left < 8) left = 8; + if (left + menuWidth > window.innerWidth - 8) { + left = Math.max(8, window.innerWidth - menuWidth - 8); + } + menu.style.position = 'fixed'; + menu.style.top = Math.round(rect.bottom + 6) + 'px'; + menu.style.left = Math.round(left) + 'px'; + menu.style.right = 'auto'; + menu.style.width = menuWidth + 'px'; + menu.style.minWidth = menuWidth + 'px'; + menu.style.maxWidth = menuWidth + 'px'; + menu.style.zIndex = '2000'; + } + + function closeMenu() { + clearCloseTimer(); + if (!openMenu) return; + openMenu.classList.remove('is-open'); + openMenu.setAttribute('hidden', ''); + openMenu.setAttribute('aria-hidden', 'true'); + if (openToggle) openToggle.setAttribute('aria-expanded', 'false'); + if (openRoot) openRoot.classList.remove('is-open'); + // Return menu to original root so SSR structure stays consistent. + if (openRoot && openMenu.parentNode !== openRoot) { + openRoot.appendChild(openMenu); + } + openRoot = null; + openMenu = null; + openToggle = null; + } + + function openMenuFor(root) { + var toggle = root.querySelector('.newadd-btns__toggle'); + var menu = root.querySelector('.drop-newadd'); + if (!toggle || !menu) return; + + if (openRoot && openRoot !== root) closeMenu(); + + clearCloseTimer(); + openRoot = root; + openMenu = menu; + openToggle = toggle; + + if (menu.parentNode !== document.body) { + document.body.appendChild(menu); + } + menu.removeAttribute('hidden'); + menu.setAttribute('aria-hidden', 'false'); + menu.classList.add('is-open'); + root.classList.add('is-open'); + toggle.setAttribute('aria-expanded', 'true'); + placeMenu(toggle, menu); + } + + function scheduleClose() { + clearCloseTimer(); + closeTimer = setTimeout(closeMenu, 160); + } + + function onPointerEnterRoot(e) { + var root = e.currentTarget; + openMenuFor(root); + } + + function onPointerLeaveRoot() { + scheduleClose(); + } + + function onPointerEnterMenu() { + clearCloseTimer(); + } + + function onPointerLeaveMenu() { + scheduleClose(); + } + + function onToggleClick(e) { + e.preventDefault(); + e.stopPropagation(); + var root = e.currentTarget.closest('[data-aksrt-newadd="1"]'); + if (!root) return; + if (openRoot === root) { + closeMenu(); + } else { + openMenuFor(root); + } + } + + function onDocPointerDown(e) { + if (!openRoot) return; + if (openRoot.contains(e.target)) return; + if (openMenu && openMenu.contains(e.target)) return; + closeMenu(); + } + + function onKey(e) { + if (e.key === 'Escape') closeMenu(); + } + + function onScrollOrResize() { + if (!openToggle || !openMenu) return; + placeMenu(openToggle, openMenu); + } + + function bindRoot(root) { + if (root.getAttribute('data-aksrt-newadd-bound') === '1') return; + root.setAttribute('data-aksrt-newadd-bound', '1'); + + var toggle = root.querySelector('.newadd-btns__toggle'); + var menu = root.querySelector('.drop-newadd'); + if (!toggle || !menu) return; + + // CSS hover no longer drives this control. + root.classList.add('is-js-portal'); + + root.addEventListener('mouseenter', onPointerEnterRoot); + root.addEventListener('mouseleave', onPointerLeaveRoot); + toggle.addEventListener('click', onToggleClick); + toggle.addEventListener('focus', function () { + openMenuFor(root); + }); + + menu.addEventListener('mouseenter', onPointerEnterMenu); + menu.addEventListener('mouseleave', onPointerLeaveMenu); + } + + function init() { + document.querySelectorAll('[data-aksrt-newadd="1"]').forEach(bindRoot); + document.addEventListener('pointerdown', onDocPointerDown, true); + document.addEventListener('keydown', onKey); + window.addEventListener('scroll', onScrollOrResize, true); + window.addEventListener('resize', onScrollOrResize); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); diff --git a/inc/helpers/aksrt-header-menu-buttons.php b/inc/helpers/aksrt-header-menu-buttons.php index b719c010..144c915a 100644 --- a/inc/helpers/aksrt-header-menu-buttons.php +++ b/inc/helpers/aksrt-header-menu-buttons.php @@ -185,13 +185,12 @@ if (!function_exists('aksrt_render_new_add_btns')) : . ''; } - $html = ''; - // type=button keeps focus without navigating; avoids link min-width quirks. - $html .= ''; - // Sibling dropdown (not a flex child of the painted chip). - $html .= '