fix(nav): portal publish menu so chip cannot stretch

Move multi-type 发布 menu to document.body with fixed positioning;
chip uses fit-content only and never inherits the 168px menu width.
This commit is contained in:
2026-07-22 10:11:59 +08:00
parent 57fa97bf9b
commit b7ee5987f0
4 changed files with 306 additions and 43 deletions
+124 -38
View File
@@ -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;
+167
View File
@@ -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();
}
})();
+4 -5
View File
@@ -185,13 +185,12 @@ if (!function_exists('aksrt_render_new_add_btns')) :
. '</a>';
}
$html = '<span class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' hover-show')) . '">';
// type=button keeps focus without navigating; avoids link min-width quirks.
$html .= '<button type="button" class="' . esc_attr(trim('but newadd-btns__toggle navbar-cta ' . $cta_class)) . '">'
// data-aksrt-newadd: JS portals the menu to body so chip width cannot track menu.
$html = '<span class="' . esc_attr(trim(implode(' ', $wrap_tokens) . ' hover-show')) . '" data-aksrt-newadd="1">';
$html .= '<button type="button" class="' . esc_attr(trim('but newadd-btns__toggle navbar-cta ' . $cta_class)) . '" aria-haspopup="menu" aria-expanded="false">'
. $label_html
. ' <i class="fas fa-caret-down" aria-hidden="true"></i></button>';
// Sibling dropdown (not a flex child of the painted chip).
$html .= '<div class="hover-show-con drop-newadd" role="menu">';
$html .= '<div class="hover-show-con drop-newadd" role="menu" hidden>';
foreach ($actions as $a) {
$html .= '<a rel="nofollow" class="newadd-btns__item" role="menuitem" href="' . esc_url($a['url']) . '">';
$html .= '<i class="' . esc_attr($a['icon']) . '" aria-hidden="true"></i> '
+11
View File
@@ -161,6 +161,17 @@ trait ScriptsPart1b {
);
}
$hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
if (file_exists($hmb_js)) {
wp_enqueue_script(
'aksrt-header-newadd',
$base_uri . '/assets/js/header-newadd.js',
[],
(string) filemtime($hmb_js),
true
);
}
// VIP modal (zibll .pay-vip)
$vip_on = class_exists('\AKSRT\Settings\Settings')
&& !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);