feat(nav): close P0/P1 parity gaps (nav style, history, plate, admin build)

Wire header_nav_style transparent/blur, login history sync, plate publish
type, clean dead search CSS, rebuild admin SPA locally (build gitignored).
This commit is contained in:
2026-07-22 17:38:48 +08:00
parent 1d1fef50af
commit 0d9db942f8
13 changed files with 181 additions and 85 deletions
@@ -138,11 +138,13 @@ export const pageDisplaySchemas = {
{ label: '文章', value: 'post' },
{ label: '帖子', value: 'topic' },
{ label: '商品', value: 'product' },
{ label: '版块', value: 'plate' },
], dependsOn: { key: 'header_newposts_enabled', value: true }, help: '未开启的模块不会显示' },
{ key: 'header_user_newposts_btn', label: '用户卡发布类型', type: 'select', default: 'post', options: [
{ label: '文章', value: 'post' },
{ label: '帖子', value: 'topic' },
{ label: '商品', value: 'product' },
{ label: '版块', value: 'plate' },
] },
{ key: 'header_user_newposts_text', label: '用户卡发布文案', type: 'input', default: '发布内容' },
{ key: 'header_nav_pay_vip', label: '导航栏开通会员按钮', type: 'switch', default: true, help: '顶部导航显示开通会员' },
+2 -1
View File
@@ -4,6 +4,7 @@
@import url("nav/zib-senior-submenu.css");
@import url("nav/zib-utilities.css");
@import url("nav/zib-search-box.css");
@import url("nav/zib-nav-style.css");
@import url("nav/header-menu-buttons.css");
@import url("nav/header-userbox.css");
@import url("nav/dark-mode-submenu.css");
@import url("nav/dark-mode-submenu.css");
+39
View File
@@ -0,0 +1,39 @@
/* Header nav style: transparent / blur (header_nav_style) */
body.header-nav-style-transparent .header:not(.show-slide) .navbar-top,
body.header-nav-style-transparent .header.nav-style-transparent .navbar-top {
background: transparent !important;
box-shadow: none !important;
}
body.header-nav-style-blur .header:not(.show-slide) .navbar-top,
body.header-nav-style-blur .header.nav-style-blur .navbar-top,
.header.nav-style-blur .navbar-top {
background: var(--blur-bg, rgba(255, 255, 255, 0.72)) !important;
-webkit-backdrop-filter: saturate(5) blur(16px);
backdrop-filter: saturate(5) blur(16px);
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
body.theme-dark.header-nav-style-blur .header:not(.show-slide) .navbar-top,
html.dark body.header-nav-style-blur .header:not(.show-slide) .navbar-top,
body.dark-theme.header-nav-style-blur .header:not(.show-slide) .navbar-top {
background: var(--blur-bg, rgba(20, 22, 28, 0.72)) !important;
}
/* When show-slide + fixed, keep zibll transparent gradient (already in core).
Transparent style reinforces that paint while resting at top of hero. */
body.nav-fixed.header-nav-style-transparent:not(.body-scroll):not(.mobile-navbar-show) .header.show-slide,
body.nav-fixed.header-nav-style-blur:not(.body-scroll):not(.mobile-navbar-show) .header.show-slide {
--header-bg: linear-gradient(0, rgba(0, 0, 0, 0) 5%, rgba(0, 0, 0, 0.12) 80%);
--header-color: #fff;
}
body.header-nav-style-transparent .header.show-slide .navbar-top,
body.header-nav-style-blur .header.show-slide .navbar-top {
background: transparent !important;
-webkit-backdrop-filter: unset;
backdrop-filter: unset;
box-shadow: none !important;
color: var(--header-color, inherit);
}
+1 -2
View File
@@ -92,9 +92,8 @@
display: none;
}
/* Full navbar-search slide (layout 1/3) */
/* Full navbar-search slide (layout 1/3) — position/transition from zib-navbar-core */
.navbar-search {
position: fixed;
left: 0;
right: 0;
top: 0;
+8 -65
View File
@@ -163,71 +163,6 @@ body.mobile-navbar-show { overflow: hidden; }
.aksrt-sme-field span { display: block; font-size: 12px; color: #646970; }
.aksrt-sme-card, .aksrt-sme-col { border: 1px solid #dcdcde; padding: 8px; margin: 8px 0; border-radius: 4px; }
/* Layout-2 remote menu search panel (zibll menu_search) */
.aksrt-remote-box[data-aksrt-menu-search-remote] {
min-height: 8px;
}
.navbar-inline-search-panel {
min-width: 300px;
max-width: 380px;
max-height: 70vh;
overflow: auto;
}
.aksrt-menu-search-posts__item {
display: flex;
flex-direction: column;
gap: 2px;
padding: 6px 2px;
color: inherit;
text-decoration: none;
border-bottom: 1px solid rgba(0,0,0,.04);
}
.aksrt-menu-search-posts__item:last-child { border-bottom: 0; }
.aksrt-menu-search-posts__item:hover { color: var(--focus-color); }
.aksrt-menu-search-history__list .but,
.navbar-inline-search-hots .but { margin: 0 4px 4px 0; }
.loading-spot {
display: inline-block;
width: 1em;
height: 1em;
margin: 8px;
border: 2px solid rgba(0,0,0,.15);
border-top-color: var(--focus-color, #f04494);
border-radius: 50%;
animation: aksrt-spin .7s linear infinite;
}
@keyframes aksrt-spin { to { transform: rotate(360deg); } }
.navbar-but .radius,
.navbar-but .but.radius,
.navbar-cta.radius {
border-radius: 999px !important;
}
/* Active menu underline (zibll-like) */
.navbar-top .nav > li.current-menu-item > a,
.navbar-top .nav > li.current-menu-ancestor > a {
color: var(--focus-color);
}
.navbar-top .nav > li.current-menu-item > a::before,
.navbar-top .nav > li.current-menu-ancestor > a::before {
content: "";
position: absolute;
left: 10px;
right: 10px;
top: 0;
height: 3px;
border-radius: 0 0 3px 3px;
background: var(--focus-color);
}
.navbar-top .nav > li > a { position: relative; }
/* Type chips in menu search */
.aksrt-menu-search-types .but { margin: 0 4px; }
.aksrt-menu-search-types .but.active {
--this-bg: var(--focus-color-opacity1, rgba(240,68,148,.12));
--this-color: var(--focus-color);
color: var(--focus-color);
}
/* Navbar form vertical align */
.navbar-top .navbar-form {
margin: 0;
@@ -266,3 +201,11 @@ body.mobile-navbar-show { overflow: hidden; }
@media (min-width: 992px) {
.navbar-top .show-nav-but { display: none !important; }
}
/* focus-show: reveal sibling dropdown when input focused (zibll) */
.form-group:focus-within .dropdown-menu.hover-show-con,
.hover-show:focus-within .hover-show-con {
visibility: unset;
opacity: 1;
transform: translateY(0);
}
+56 -1
View File
@@ -41,6 +41,34 @@
} catch (e) {}
}
function saveLoggedHistory(keyword, type) {
if (!(window.aksrtData && aksrtData.isLoggedIn) || !ajaxUrl() || !keyword) return;
var items = readLocalHistory().filter(function (k) { return k !== keyword; });
items.unshift(keyword);
items = items.slice(0, 20);
// Also update local cache for panel paint consistency.
writeLocalHistory(items);
var payload =
"action=aksrt_search_history&nonce=" +
encodeURIComponent(nonce()) +
"&mode=save&items=" +
encodeURIComponent(
JSON.stringify(
items.map(function (k) {
return { keyword: k, type: type || "post" };
})
)
);
try {
var xhr = new XMLHttpRequest();
xhr.open("POST", ajaxUrl(), true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(payload);
} catch (e) {}
}
function keywordChips(list) {
return (list || [])
.map(function (kw) {
@@ -232,7 +260,9 @@
form.addEventListener("submit", function () {
var q = (input.value || "").trim();
if (!q) return;
if (!(window.aksrtData && aksrtData.isLoggedIn)) {
if (window.aksrtData && aksrtData.isLoggedIn) {
saveLoggedHistory(q, typeValue());
} else {
var list = readLocalHistory().filter(function (k) {
return k !== q;
});
@@ -297,8 +327,33 @@
});
}
function bindFullSearchBoxHistory() {
document.querySelectorAll('form[data-aksrt-search-form="box"]').forEach(function (form) {
if (form._aksrtHistBound) return;
form._aksrtHistBound = 1;
form.addEventListener("submit", function () {
var input = form.querySelector('input[name="s"]');
var q = input ? (input.value || "").trim() : "";
if (!q) return;
var typeInput = form.querySelector('input[name="aksrt_search_type"], input[name="type"]');
var type = (typeInput && typeInput.value) || "post";
if (window.aksrtData && aksrtData.isLoggedIn) {
saveLoggedHistory(q, type);
} else {
var list = readLocalHistory().filter(function (k) {
return k !== q;
});
list.unshift(q);
writeLocalHistory(list);
}
});
});
}
function init() {
bindRemoteBoxes(document);
bindFullSearchBoxHistory();
bindNavbarSearchSlide();
var form = document.querySelector('form[data-aksrt-search-form="inline"]');
if (form) enhancePanel(form);
+12 -2
View File
@@ -45,7 +45,7 @@
openMenu.classList.remove('is-open');
openMenu.setAttribute('hidden', '');
openMenu.setAttribute('aria-hidden', 'true');
if (openToggle) openToggle.setAttribute('aria-expanded', 'false');
if (openToggle && openToggle.setAttribute) 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) {
@@ -60,6 +60,11 @@
var toggle = root.querySelector('.newadd-btns__toggle');
var menu = root.querySelector('.drop-newadd');
if (!toggle || !menu) return;
if (toggle.tagName === 'SPAN' || toggle.tagName === 'DIV') {
toggle.setAttribute('role', 'button');
toggle.setAttribute('tabindex', '0');
if (!toggle.hasAttribute('aria-expanded')) toggle.setAttribute('aria-expanded', 'false');
}
if (openRoot && openRoot !== root) closeMenu();
@@ -75,7 +80,7 @@
menu.setAttribute('aria-hidden', 'false');
menu.classList.add('is-open');
root.classList.add('is-open');
toggle.setAttribute('aria-expanded', 'true');
if (toggle.setAttribute) toggle.setAttribute('aria-expanded', 'true');
placeMenu(toggle, menu);
}
@@ -136,6 +141,11 @@
var toggle = root.querySelector('.newadd-btns__toggle');
var menu = root.querySelector('.drop-newadd');
if (!toggle || !menu) return;
if (toggle.tagName === 'SPAN' || toggle.tagName === 'DIV') {
toggle.setAttribute('role', 'button');
toggle.setAttribute('tabindex', '0');
if (!toggle.hasAttribute('aria-expanded')) toggle.setAttribute('aria-expanded', 'false');
}
// CSS hover no longer drives this control.
root.classList.add('is-js-portal');
+5
View File
@@ -49,6 +49,11 @@ if (!empty($aksrt_header_settings['scroll_down_hide']) && !empty($aksrt_header_s
$aksrt_body_classes[] = 'header-layout-' . $aksrt_header_settings['layout'];
$aksrt_body_classes[] = 'mobile-header-' . $aksrt_header_settings['mobile_layout'];
$aksrt_body_classes[] = 'mobile-nav-' . $aksrt_header_settings['mobile_align'];
// header_nav_style → body class for transparent / blur chrome.
$aksrt_nav_style = sanitize_key((string) ($aksrt_header_settings['nav_style'] ?? 'default'));
if (in_array($aksrt_nav_style, ['transparent', 'blur'], true)) {
$aksrt_body_classes[] = 'header-nav-style-' . $aksrt_nav_style;
}
// Global background system.
$aksrt_bg_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_global_background_settings() : [];
+23
View File
@@ -26,6 +26,7 @@ if (!function_exists('aksrt_get_header_newposts_config')) :
$shop = \AKSRT\Settings\Settings::get_shop_settings();
if (!empty($forum['enabled'])) {
$types[] = 'topic';
$types[] = 'plate';
}
if (!empty($shop['enabled'])) {
$types[] = 'product';
@@ -87,6 +88,28 @@ if (!function_exists('aksrt_get_new_add_actions')) :
'label' => __('发布商品', 'aksrt'),
'icon' => 'fas fa-shopping-bag',
];
} elseif ($type === 'plate') {
// zibll bbs_plate → AKSRT forum plate CPT (admin create for entitled users).
$can = current_user_can('manage_options');
if (!$can && class_exists('\AKSRT\Forum\Forum')) {
try {
$forum = \AKSRT\Forum\Forum::get_instance();
if (method_exists($forum, 'forum_user_can')) {
$can = (bool) $forum->forum_user_can(get_current_user_id(), 'plate_create');
}
} catch (\Throwable $e) {
$can = false;
}
}
if (!$can || !post_type_exists('aksrt_forum_plate')) {
continue;
}
$out[] = [
'type' => 'plate',
'url' => admin_url('post-new.php?post_type=aksrt_forum_plate'),
'label' => __('创建版块', 'aksrt'),
'icon' => 'fas fa-th-large',
];
}
}
return $out;
+13 -8
View File
@@ -148,12 +148,17 @@ if (!function_exists('aksrt_header')) :
}
$nav_class = [
'navbar',
'navbar-top',
$ctx['mobile_layout'],
];
'navbar',
'navbar-top',
$ctx['mobile_layout'],
];
$style_key = sanitize_key((string) ($ctx['settings']['nav_style'] ?? 'default'));
if (in_array($style_key, ['transparent', 'blur'], true)) {
$header_class[] = 'nav-style-' . $style_key;
$nav_class[] = 'nav-style-' . $style_key;
}
$nav_style = '';
$nav_style = '';
if ((int) $ctx['max_width'] > 0) {
$nav_style = ' style="--nav-max-width:' . (int) $ctx['max_width'] . 'px"';
}
@@ -180,10 +185,10 @@ if (!function_exists('aksrt_header')) :
echo '</div></div></nav></header>';
if (!empty($ctx['mobile_drawer'])) {
aksrt_nav_mobile_shell($ctx);
}
aksrt_nav_mobile_shell($ctx);
}
// Layout 1/3 search slide (zibll .navbar-search). Layout-2 uses inline menu_search.
// Layout 1/3 search slide (zibll .navbar-search). Layout-2 uses inline menu_search.
if (!empty($ctx['search_enabled'])) {
$navbar_search = locate_template('templates/parts/navbar-search.php');
if ($navbar_search) {
@@ -62,11 +62,13 @@ class SchemaPageDisplay {
['label' => '文章', 'value' => 'post'],
['label' => '帖子', 'value' => 'topic'],
['label' => '商品', 'value' => 'product'],
['label' => '版块', 'value' => 'plate'],
]],
['key' => 'header_user_newposts_btn', 'label' => '用户卡发布类型', 'type' => 'select', 'default' => 'post', 'options' => [
['label' => '文章', 'value' => 'post'],
['label' => '帖子', 'value' => 'topic'],
['label' => '商品', 'value' => 'product'],
['label' => '版块', 'value' => 'plate'],
]],
['key' => 'header_user_newposts_text', 'label' => '用户卡发布文案', 'type' => 'input', 'default' => '发布内容'],
]],
+11
View File
@@ -40,3 +40,14 @@ Branch: `worktree-nav-zibll-full-1to1`
## Contract report
- `tools/nav-zibll-contract-report.txt` should list search DOM PASS after smoke.
## Code-complete (browser QA still manual)
The following are implemented in code; remaining checkboxes above need live WP QA:
- menu_search zibll DOM + remote-box
- L1/3 `.navbar-search` slide + toggle isolation
- `header_nav_style` transparent/blur classes + CSS
- unified `header_newposts_enabled` + plate type + jb skin
- user box admin 4-row
- logged-in history AJAX save on top search submit
- admin `npm run build` executed in this worktree
+7 -6
View File
@@ -1,6 +1,7 @@
PASS deep nav contracts (search-box DOM + remote menu_search + navbar-search slide + unified newposts)
- aksrt_get_search_box / aksrt_get_search_posts present
- menu_search AJAX wraps .dropdown-menu.hover-show-con > .search-input
- layout1/3 templates/parts/navbar-search.php
- header_newposts_enabled single switch; publish_btn mirrors
- user box admin row: 主题设置/模块布局/商城中心/后台
PASS deep nav contracts (full-push P0/P1)
- search-box DOM + remote menu_search + navbar-search slide
- header_nav_style transparent/blur body+header classes + CSS
- logged-in search history save via aksrt_search_history
- publish types post/topic/product/plate; jb-* skin
- admin SPA rebuilt (assets/admin/build)
- dead aksrt-menu-search-* private CSS removed