diff --git a/assets/admin/src/schema/sections/page-display/index.js b/assets/admin/src/schema/sections/page-display/index.js index 8b2f05aa..659a813a 100644 --- a/assets/admin/src/schema/sections/page-display/index.js +++ b/assets/admin/src/schema/sections/page-display/index.js @@ -37,6 +37,7 @@ export const pageDisplaySchemas = { header_nav_pay_vip: true, header_nav_user_pay_vip: true, header_newposts_types: ['post'], + header_user_newposts_btn: 'post', header_user_newposts_text: '发布内容', mobile_header_layout: 'center', mobile_navbar_align: 'left', @@ -124,6 +125,11 @@ export const pageDisplaySchemas = { { label: '帖子', value: 'topic' }, { label: '商品', value: 'product' }, ], 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' }, + ] }, { key: 'header_user_newposts_text', label: '用户卡发布文案', type: 'input', default: '发布内容' }, { key: 'header_nav_pay_vip', label: '导航栏开通会员按钮', type: 'switch', default: true, help: '顶部导航显示开通会员' }, { key: 'header_nav_user_pay_vip', label: '用户框开通会员按钮', type: 'switch', default: true }, diff --git a/assets/css/frontend/nav.css b/assets/css/frontend/nav.css index 10fd9882..207f608b 100644 --- a/assets/css/frontend/nav.css +++ b/assets/css/frontend/nav.css @@ -2,10 +2,7 @@ @import url("nav/zib-navbar-core.css"); @import url("nav/zib-mobile-navbar.css"); @import url("nav/zib-senior-submenu.css"); -@import url("nav/dark-mode-submenu.css"); -@import url("nav/dark-mode-mega-menu.css"); +@import url("nav/zib-utilities.css"); @import url("nav/header-menu-buttons.css"); @import url("nav/header-userbox.css"); -@import url("nav/menu-item-icon.css"); -@import url("nav/menu-item-badge.css"); -@import url("nav/hover-effects.css"); +@import url("nav/dark-mode-submenu.css"); diff --git a/assets/css/frontend/nav/base.css b/assets/css/frontend/nav/base.css deleted file mode 100644 index 949134e5..00000000 --- a/assets/css/frontend/nav/base.css +++ /dev/null @@ -1,577 +0,0 @@ -/* Zibll body.nav-fixed: hard 88px reserve (main.css), not bare --nav-height. - * Nav bar itself is ~60px; extra space matches zibll chrome/shadow gap. - * --nav-fixed-reserve is shared with the hero pull-up so they cancel exactly - * (zibll: body padding-top 88px + .slide-header { margin-top: -90px }). */ -body.nav-fixed { - --nav-fixed-reserve: 88px; - padding-top: var(--nav-fixed-reserve); -} - -@media (max-width: 768px) { - body.nav-fixed { - --nav-fixed-reserve: 72px; - padding-top: var(--nav-fixed-reserve); - } -} - -@media (max-width: 640px) { - body.nav-fixed { - --nav-fixed-reserve: 60px; - padding-top: var(--nav-fixed-reserve); - } -} - -/* Fixed nav without hero overlay: take header out of flow. - body.nav-fixed already reserves space via padding-top. */ -body.nav-fixed .header:not(.show-slide) { - position: fixed; - top: 0; - left: 0; - right: 0; - width: 100%; - z-index: 1000; -} - -/* Nav lives inside the fixed header — don't keep sticky (double offset). */ -body.nav-fixed .header:not(.show-slide) .site-nav, -body.nav-fixed .header:not(.show-slide) .navbar.navbar-top { - position: relative; - top: auto; -} - -/* - * Non-home pages have no hero under the fixed header. Keep the first content - * (breadcrumb / article) clearly below the bar even if a fluid widget zone is - * empty or a child uses negative margin. - */ -body.nav-fixed:not(:has(.header.show-slide)) .fluid-widget-wrap:first-of-type:empty + main.container, -body.nav-fixed:not(:has(.header.show-slide)) main.container:first-of-type { - scroll-margin-top: calc(var(--nav-fixed-reserve, 88px) + 8px); -} - -/* Hero sits under transparent fixed/absolute header. - * MUST cancel the full --nav-fixed-reserve (88/72/60), not just --nav-height (60). - * Using only -60px against 88px padding left a ~28px blank strip above the hero. */ -body.nav-fixed .header-slider-container, -body.nav-fixed .header-components-container, -body.nav-fixed .header-components.slide-header { - margin-top: calc(var(--nav-fixed-reserve, 88px) * -1) !important; - position: relative; - z-index: 1; -} - -/* ============================================================ - * AKSRT Navigation — Zibll-aligned - * - * - 高度 60px (--nav-height) - * - 毛玻璃 blur-bg(saturate(5) blur(20px)) - * - 透明叠 slider → 滚动后恢复实底 - * - 滚动隐藏(scroll-down-hide 等价) - * ============================================================ */ - -.site-nav { - position: sticky; - top: 0; - z-index: 1000; - min-height: var(--nav-height, 60px); - background-color: var(--blur-bg); - border-bottom: 1px solid rgba(255, 255, 255, 0.45); - backdrop-filter: saturate(5) blur(20px); - -webkit-backdrop-filter: saturate(5) blur(20px); - transition: background-color 0.25s ease, - border-color 0.25s ease, - color 0.25s ease, - box-shadow 0.25s ease, - transform 0.3s ease; /* 滚动隐藏过渡 */ -} - -/* 滚动隐藏头部 — 对齐 zibll .scroll-down.nav-fixed .header.scroll-down-hide */ -.site-nav.is-hidden { - transform: translateY(-105%); -} - -.site-nav--static { - position: relative; -} - -.site-nav--transparent { - background: transparent; /* 对齐 zibll .header.show-slide: 透明覆盖在 slider 上 */ - border-bottom-color: transparent; -} - -.site-nav--transparent:not(.is-scrolled) { - --header-color: #fff; /* 对齐 zibll --header-color:#fff */ - color: #fff; -} - -.site-nav--transparent:not(.is-scrolled) a { - color: inherit; -} - -.site-nav--transparent.is-scrolled { - background: var(--blur-bg); /* 滚动后恢复毛玻璃背景 */ - border-bottom-color: var(--color-line-soft); -} - -.site-nav--blur { - background: var(--blur-bg); - backdrop-filter: saturate(5) blur(20px); - -webkit-backdrop-filter: saturate(5) blur(20px); - border-bottom-color: transparent; -} - -html.dark .site-nav--transparent:not(.is-scrolled), -html.dark .site-nav--blur:not(.is-scrolled), -body.dark-theme .site-nav--transparent:not(.is-scrolled), -body.dark-theme .site-nav--blur:not(.is-scrolled) { - background: transparent; - border-bottom-color: transparent; -} - -html.dark .site-nav--transparent.is-scrolled, -html.dark .site-nav--blur.is-scrolled, -body.dark-theme .site-nav--transparent.is-scrolled, -body.dark-theme .site-nav--blur.is-scrolled { - background: var(--blur-bg); - border-bottom-color: var(--color-line-soft); -} - -/* 滚动后追加阴影 — 对齐 zibll .body-scroll .header */ -.site-nav.is-scrolled { - box-shadow: 0 4px 10px var(--main-shadow, var(--shadow-sm)); -} - -/* WordPress Admin Bar 已全局禁用,无需偏移规则 */ - -/* ============================================================ - * Inner / Row layout - * ============================================================ */ -.site-nav__inner { - max-width: var(--nav-max-width, var(--container)); - margin: 0 auto; - padding: 0 16px; - display: flex; - flex-direction: column; - gap: 0; -} - -.site-nav__row { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 12px; - width: 100%; - min-height: var(--nav-height, 60px); -} - -/* ============================================================ - * Brand - * ============================================================ */ -.site-brand { - display: inline-flex; - align-items: center; - gap: 10px; - min-width: 0; - max-width: min(48vw, 360px); - padding: 7px 10px; - color: var(--color-ink); - font-size: 17px; - font-weight: 700; - letter-spacing: -0.01em; - flex-shrink: 0; - text-decoration: none; -} - -.site-brand:hover { - color: var(--color-ink); - text-decoration: none; -} - -.site-brand--has-logo { - gap: 0; -} - -.site-brand__logo { - width: 36px; - height: 36px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - font-weight: 800; - font-size: 13px; - color: var(--color-on-primary, #fff); - background: linear-gradient(135deg, var(--color-primary), var(--color-primary-active, var(--color-primary-dark))); - letter-spacing: 0.02em; - overflow: hidden; -} - -.site-brand__media { - display: block; - flex: 0 1 auto; - max-width: 100%; - padding: 0 30px; - line-height: 0; - box-sizing: border-box; - background: transparent !important; - border: 0; - border-radius: 0; - box-shadow: none; - filter: none !important; - opacity: 1; -} - -.site-brand__img { - display: block; - height: 36px; - width: auto; - max-width: 100%; - object-fit: contain; - object-position: left center; - background: transparent !important; - border-radius: 0; - box-shadow: none; - filter: none !important; - mix-blend-mode: normal !important; - opacity: 1; - transform: none !important; -} - -.site-brand__name { - font-weight: 700; - letter-spacing: -0.01em; - white-space: nowrap; -} - -/* Light/dark logo: single adaptive img (white-src/dark-src via theme.js) */ -.navbar-logo > img, -.navbar-logo .site-brand__logo-img, -.site-brand .site-brand__logo-img, -.site-brand__logo-img, -.site-brand .navbar-logo img { - height: 36px !important; - width: auto !important; - max-width: min(180px, 40vw) !important; - max-height: 36px !important; - padding: 0 !important; - object-fit: contain !important; - display: inline-block; - vertical-align: middle; -} - -/* Legacy dual-img classes (if any remain elsewhere) */ -.site-brand__logo-img--dark { - display: none; -} - -html.dark .site-brand__logo-img--light, -[data-theme="dark"] .site-brand__logo-img--light, -body.dark-theme .site-brand__logo-img--light { - display: none; -} - -html.dark .site-brand__logo-img--dark, -[data-theme="dark"] .site-brand__logo-img--dark, -body.dark-theme .site-brand__logo-img--dark { - display: inline-block; -} - -/* ============================================================ - * Desktop menu - * ============================================================ */ -ul.nav-desktop { - display: none; - list-style: none; - margin: 0; - padding: 0; - align-items: center; - flex: 1 1 auto; - min-width: 0; -} - -.nav-desktop--fallback { - display: none; - align-items: center; - flex: 1 1 auto; - min-width: 0; -} - -ul.nav-desktop a, -.nav-desktop--fallback a { - color: var(--color-ink-3); - font-size: 14px; - font-weight: 500; - padding: 0 12px; /* 对齐 zibll:仅水平 padding,垂直居中靠 flex 行高 */ - border-radius: 4px; - transition: color var(--dur-fast, 0.15s) var(--ease), - background var(--dur-fast, 0.15s) var(--ease); -} - -/* Hover — 对齐 zibll: 仅变色,无背景 */ -ul.nav-desktop a:hover, -.nav-desktop--fallback a:hover { - color: var(--color-primary); - background: transparent; -} - -/* Active page — 对齐 zibll: 仅变色(指示器走下方胶囊条) */ -ul.nav-desktop .current-menu-item > a, -ul.nav-desktop .current_page_item > a { - color: var(--color-primary); - background: transparent; -} - -/* ============================================================ - * Desktop submenu (dropdown) - * ============================================================ */ -ul.nav-desktop .menu-item { - position: relative; -} - -/* 顶部 hover/current 胶囊指示器 — 对齐 zibll .navbar-nav>li:before - (5px 高、底部 15px 圆角,从 header 顶缘垂下)。 - stretch 链(row→ul→li)让 li 充满 60px 行高,::before top:0 即锚定 header 顶部; - ::before 为 absolute 不进入 flex 流,不挤压链接。 */ -ul.nav-desktop { - align-self: stretch; -} - -ul.nav-desktop > .menu-item { - align-self: stretch; - display: flex; - align-items: center; -} - -ul.nav-desktop > .menu-item::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 5px; - background: var(--focus-color, var(--color-primary)); - border-radius: 0 0 15px 15px; - opacity: 0; - transition: opacity 0.3s; - pointer-events: none; -} - -ul.nav-desktop > .menu-item:hover::before, -ul.nav-desktop > .current-menu-item::before, -ul.nav-desktop > .current_page_item::before { - opacity: 1; -} - -ul.nav-desktop .sub-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 998; /* 保留较高 z-index(zibll 用 99,AKSRT 栈更深,避免被覆盖) */ - min-width: 140px; - list-style: none; - margin: 8px 0 0; - padding: 8px 6px; - background: var(--main-bg-color, #fff); - border: none; - border-radius: var(--main-radius, var(--radius, 8px)); - box-shadow: var(--shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(6px); - transition: opacity 0.4s ease, transform 0.4s ease, visibility 0.4s ease; -} - -ul.nav-desktop .menu-item:hover > .sub-menu { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -ul.nav-desktop .sub-menu .menu-item > a { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 15px; - font-size: 14px; - border-radius: 4px; - white-space: nowrap; -} - -ul.nav-desktop .sub-menu .menu-item > a:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); - color: var(--color-primary); -} - -/* Nested submenus fly out to the right — 对齐 zibll top:-10px,去 margin-left */ -ul.nav-desktop .sub-menu .sub-menu { - top: -10px; - left: 100%; - margin: 0; -} - - - -/* ============================================================ - * Zibll .header.show-slide — transparent gradient over hero - * ============================================================ */ -.header.show-slide { - --header-bg: linear-gradient(0, rgba(0, 0, 0, 0) 5%, rgba(0, 0, 0, 0.1) 80%); - --header-color: #fff; - -webkit-backdrop-filter: unset; - backdrop-filter: unset; -} - -body.nav-fixed .header.show-slide { - position: absolute !important; - top: 0; - left: 0; - right: 0; - width: 100%; - z-index: 30; - background: transparent !important; - box-shadow: none !important; - border: 0 !important; -} - -/* Nav inside absolute header must not use sticky (avoids double offset) */ -body.nav-fixed .header.show-slide .site-nav, -body.nav-fixed .header.show-slide .navbar.navbar-top { - position: relative !important; - top: auto !important; - background: var(--header-bg, transparent) !important; - border-bottom-color: transparent !important; - box-shadow: none !important; - color: var(--header-color, #fff); - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; -} - -.header.show-slide .navbar.navbar-top, -.header.show-slide .site-nav { - background: var(--header-bg, transparent); - border-bottom-color: transparent; - box-shadow: none; - color: var(--header-color, #fff); - backdrop-filter: none; - -webkit-backdrop-filter: none; -} - -.header.show-slide .site-nav:not(.is-scrolled) a, -.header.show-slide .site-nav:not(.is-scrolled) .icon-btn, -.header.show-slide .site-nav:not(.is-scrolled) .site-brand__name { - color: #fff; -} - -.header.show-slide .site-nav.is-scrolled, -.site-nav.is-scrolled { - background: var(--blur-bg); - color: var(--header-color, var(--color-ink-2)); - border-bottom-color: rgba(255, 255, 255, 0.45); - backdrop-filter: saturate(5) blur(20px); - -webkit-backdrop-filter: saturate(5) blur(20px); - box-shadow: 0 4px 10px var(--main-shadow, rgba(116, 116, 116, 0.08)); -} - -.navbar.navbar-top { - margin: 0; - border-radius: 0 !important; - font-size: 15px; -} - -.container-header, -.container-footer { - max-width: calc(var(--mian-max-width, var(--container, 1200px)) + 180px); - margin-left: auto; - margin-right: auto; - width: 100%; - padding-left: 15px; - padding-right: 15px; -} - -.navbar-top .navbar-brand { - padding: 7px 10px; -} - -.navbar-logo > img, -.navbar-logo .site-brand__logo-img, -.site-brand .site-brand__logo-img, -.site-brand__logo-img { - height: 36px !important; - width: auto !important; - max-width: min(180px, 40vw) !important; - max-height: 36px !important; - padding: 0 !important; - object-fit: contain !important; -} - -.navbar-top .navbar-nav, -.navbar-top ul.nav-desktop { - margin-left: 20px; - margin-right: 20px; - display: flex; - align-items: center; - gap: 0; - list-style: none; - padding: 0; -} - -.navbar-top .navbar-nav > li > a, -.navbar-top ul.nav-desktop > li > a { - padding-left: 10px; - padding-right: 10px; - border-radius: 4px; - display: inline-flex !important; - align-items: center; - min-height: 36px; - font-size: 15px; -} - -.navbar-top .site-nav__row { - display: flex; - align-items: center; - width: 100%; - min-height: var(--nav-height, 60px); -} - -.navbar-top .nav-actions { - margin-left: auto; - display: flex; - align-items: center; - gap: 8px; - overflow: visible; - position: relative; - z-index: 25; -} - -.scroll-down.nav-fixed .header.scroll-down-hide, -body.scroll-down.nav-fixed .header.scroll-down-hide { - transform: translate3d(0, -105%, 0); - -webkit-backdrop-filter: none; - backdrop-filter: none; -} - - -/* Layout-1 style: keep search as icon; hide expanded desktop form */ -@media (min-width: 992px) { - .navbar-top .nav-searchbox--desktop { - display: none !important; - } -} - -/* Transparent white controls on gradient hero */ -.header.show-slide .site-nav:not(.is-scrolled) .btn-outline { - color: #fff; - border-color: rgba(255, 255, 255, 0.55); - background: transparent; -} - -.header.show-slide .site-nav:not(.is-scrolled) .btn-outline:hover { - color: #fff; - border-color: #fff; - background: rgba(255, 255, 255, 0.12); -} - -.header.show-slide .site-nav:not(.is-scrolled) .nav-user__guest-avatar, -.header.show-slide .site-nav:not(.is-scrolled) .icon-btn { - color: #fff; -} diff --git a/assets/css/frontend/nav/cards-submenu.css b/assets/css/frontend/nav/cards-submenu.css deleted file mode 100644 index 272b996d..00000000 --- a/assets/css/frontend/nav/cards-submenu.css +++ /dev/null @@ -1,128 +0,0 @@ -/* Cards submenu */ -.aksrt-nav__cards { - display: grid; - gap: 12px; - padding: 8px; -} - -.aksrt-nav__card { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 12px; - border-radius: 6px; - text-decoration: none; - color: inherit; - transition: background 0.15s; -} - -.aksrt-nav__card:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.06)); -} - -.aksrt-nav__card-icon { - width: 36px; - height: 36px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - background: var(--color-primary-soft, #e6f4ff); - color: var(--color-primary); - font-size: 16px; - flex-shrink: 0; -} - -.aksrt-nav__card-text { - flex: 1; - min-width: 0; -} - -.aksrt-nav__card-title { - font-size: 13px; - font-weight: 600; - color: var(--color-ink); - margin: 0; -} - -.aksrt-nav__card-desc { - font-size: 11px; - color: var(--color-ink-4); - margin: 2px 0 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* ============================================================ - * 导航溢出「更多」下拉 - * ============================================================ */ -.aksrt-nav-more { - position: relative; -} - -.aksrt-nav-more__btn { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 6px 12px; - border: none; - background: none; - color: var(--color-ink-2); - font-size: 14px; - font-weight: 500; - cursor: pointer; - border-radius: var(--radius, 8px); - transition: background 0.15s, color 0.15s; -} - -.aksrt-nav-more__btn:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); - color: var(--color-primary); -} - -.aksrt-nav-more__dropdown { - display: none; - position: absolute; - top: 100%; - right: 0; - min-width: 160px; - padding: 6px 0; - background: var(--surface-1, #fff); - border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06)); - border-radius: var(--radius, 8px); - box-shadow: var(--shadow-lg, 0 0 10px rgba(116, 116, 116, 0.12)); - z-index: var(--z-dropdown, 100); - list-style: none; - margin: 4px 0 0; -} - -.aksrt-nav-more__dropdown.is-open { - display: block; -} - -.aksrt-nav-more__dropdown li { - display: block; -} - -.aksrt-nav-more__dropdown li a, -.aksrt-nav-more__dropdown li button { - display: block; - width: 100%; - padding: 8px 16px; - border: none; - background: none; - color: var(--color-ink-2); - font-size: 14px; - text-align: left; - text-decoration: none; - cursor: pointer; - transition: background 0.15s, color 0.15s; -} - -.aksrt-nav-more__dropdown li a:hover, -.aksrt-nav-more__dropdown li button:hover { - background: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); - color: var(--color-primary); -} - diff --git a/assets/css/frontend/nav/dark-mode-mega-menu.css b/assets/css/frontend/nav/dark-mode-mega-menu.css deleted file mode 100644 index 28994298..00000000 --- a/assets/css/frontend/nav/dark-mode-mega-menu.css +++ /dev/null @@ -1,12 +0,0 @@ -/* Dark mode Mega Menu */ -html.dark ul.nav-desktop .mega-menu-item > .mega-menu__panel, -body.dark-theme ul.nav-desktop .mega-menu-item > .mega-menu__panel { - background: var(--surface-page); - border-color: var(--color-line, #2d2d3f); -} - -html.dark .mega-menu__panel > .menu-item:hover, -body.dark-theme .mega-menu__panel > .menu-item:hover { - background: var(--surface-2); -} - diff --git a/assets/css/frontend/nav/hover-effects.css b/assets/css/frontend/nav/hover-effects.css deleted file mode 100644 index 2e127318..00000000 --- a/assets/css/frontend/nav/hover-effects.css +++ /dev/null @@ -1,35 +0,0 @@ -/* Hover effects */ -.aksrt-nav__item--hover-underline > a::after { - content: ''; - position: absolute; - bottom: 0; - left: 50%; - width: 0; - height: 2px; - background: var(--color-primary); - transition: width 0.2s ease, left 0.2s ease; - border-radius: 1px; -} - -.aksrt-nav__item--hover-underline:hover > a::after { - width: 60%; - left: 20%; -} - -.aksrt-nav__item--hover-background > a { - transition: background-color 0.2s; - border-radius: 4px; -} - -.aksrt-nav__item--hover-background:hover > a { - background-color: var(--color-primary-soft, rgba(240, 68, 148, 0.08)); -} - -.aksrt-nav__item--hover-color > a { - transition: color 0.2s; -} - -.aksrt-nav__item--hover-color:hover > a { - color: var(--color-primary); -} - diff --git a/assets/css/frontend/nav/mega-submenu.css b/assets/css/frontend/nav/mega-submenu.css deleted file mode 100644 index d41a4464..00000000 --- a/assets/css/frontend/nav/mega-submenu.css +++ /dev/null @@ -1,28 +0,0 @@ -/* Mega submenu */ -.aksrt-nav__mega { - position: absolute; - top: 100%; - left: 0; - z-index: 1001; - background: var(--surface-1); - border: 1px solid var(--color-line); - border-radius: var(--radius); - box-shadow: var(--shadow-lg); - padding: 16px; - opacity: 0; - visibility: hidden; - transform: translateY(8px); - transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; -} - -.aksrt-nav__item:hover > .aksrt-nav__mega { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -.aksrt-nav__mega--columns { - display: grid; - gap: 16px; -} - diff --git a/assets/css/frontend/nav/menu-item-badge.css b/assets/css/frontend/nav/menu-item-badge.css deleted file mode 100644 index 5a6b5379..00000000 --- a/assets/css/frontend/nav/menu-item-badge.css +++ /dev/null @@ -1,41 +0,0 @@ -/* Menu item badge */ -.aksrt-nav__badge { - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 10px; - font-weight: 600; - line-height: 1; - padding: 2px 5px; - border-radius: 3px; - margin-left: 4px; - white-space: nowrap; - vertical-align: middle; - transform: translateY(-1px); -} - -.aksrt-nav__badge--new { - color: #fff; - background: var(--color-error); -} - -.aksrt-nav__badge--hot { - color: #fff; - background: var(--color-warning); -} - -.aksrt-nav__badge--info { - color: #fff; - background: var(--color-info); -} - -.aksrt-nav__badge--success { - color: #fff; - background: var(--color-success); -} - -.aksrt-nav__badge--vip { - color: #fff; - background: linear-gradient(135deg, var(--color-warning), var(--color-error)); -} - diff --git a/assets/css/frontend/nav/menu-item-icon.css b/assets/css/frontend/nav/menu-item-icon.css deleted file mode 100644 index 67ccce61..00000000 --- a/assets/css/frontend/nav/menu-item-icon.css +++ /dev/null @@ -1,20 +0,0 @@ -/* Menu item icon */ -.aksrt-nav__icon { - font-size: 0.85em; - width: 1.2em; - text-align: center; - margin-right: 4px; - opacity: 0.7; - transition: opacity 0.2s; -} - -.aksrt-nav__item--has-icon > a { - display: inline-flex; - align-items: center; - gap: 4px; -} - -.aksrt-nav__item--has-icon:hover .aksrt-nav__icon { - opacity: 1; -} - diff --git a/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css b/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css deleted file mode 100644 index 728acaf9..00000000 --- a/assets/css/frontend/nav/mobile-theme-toggle-in-drawer.css +++ /dev/null @@ -1,18 +0,0 @@ -/* Mobile theme toggle in drawer */ -.nav-drawer__theme-toggle { - padding: 0 20px 16px; -} - -.nav-drawer__theme-toggle .theme-toggle-mobile { - width: 100%; - min-height: 44px; - justify-content: center; - gap: 8px; - display: flex; - align-items: center; -} - -/* ============================================================ - * Menu Decoration — Icons, Badges, Hover Effects - * ============================================================ */ - diff --git a/assets/css/frontend/nav/mobile-toggle.css b/assets/css/frontend/nav/mobile-toggle.css deleted file mode 100644 index 134bc6c7..00000000 --- a/assets/css/frontend/nav/mobile-toggle.css +++ /dev/null @@ -1,814 +0,0 @@ -/* Mobile toggle */ -.nav-toggle { - display: flex; -} - -@media (max-width: 991px) { - .site-brand { - max-width: min(46vw, 311px); - } - - .site-brand__media { - padding: 0 8px; - } - - .nav-publish-btn { - display: none; - } -} - -/* Desktop search icon: hide on mobile (use drawer search instead) */ -@media (max-width: 767px) { - .site-brand { - max-width: min(62vw, 260px); - padding: 7px 0; - } - - .site-brand__media { - padding: 0; - } - - #search-toggle { - display: none; - } - /* Search panel only makes sense alongside the desktop search icon */ - .nav-search-panel { - display: none !important; - } -} - -@media (min-width: 768px) { - ul.nav-desktop, - .nav-desktop--fallback { - display: flex; - } - - .nav-auth { - display: flex; - } - - .nav-auth-dropdown { - display: flex; - } - - .nav-toggle { - display: none; - } -} - -/* ============================================================ - * Header Layout Variants (desktop ≥768px) - * Layout 1: Standard — brand left, nav flex-1, actions right - * Layout 2: Centered — brand left, nav centered with flex, actions right - * Layout 3: Compact — brand left, nav pushed right, actions right - * ============================================================ */ -@media (min-width: 768px) { - /* Layout 2: center the nav between brand and actions */ - body.header-layout-2 .nav-desktop { - flex: 1; - justify-content: center; - } - - body.header-layout-2 .nav-actions { - flex-shrink: 0; - } - - /* Layout 3: push nav to the right side */ - body.header-layout-3 .site-nav__row { - justify-content: flex-start; - } - - body.header-layout-3 .nav-desktop { - flex: 1; - justify-content: flex-end; - margin-left: 24px; - } - - body.header-layout-3 .nav-actions { - margin-left: 8px; - } -} - -.nav-mobile-strip { - display: none; - width: calc(100% + 8px); - margin: 0 -4px; - padding: 0 0 12px; -} - -.nav-mobile-strip__menu, -.nav-mobile-strip__menu ul { - display: flex; - align-items: center; - gap: 8px; - overflow-x: auto; - margin: 0; - padding: 0; - list-style: none; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.nav-mobile-strip__menu::-webkit-scrollbar, -.nav-mobile-strip__menu ul::-webkit-scrollbar { - display: none; -} - -.nav-mobile-strip__menu a { - display: inline-flex; - align-items: center; - min-height: 34px; - padding: 0 12px; - border-radius: var(--radius-pill, 999px); - background: var(--surface-2); - color: var(--color-ink-2); - white-space: nowrap; - text-decoration: none; - font-size: 0.875rem; - font-weight: 500; -} - -.nav-mobile-strip__menu .current-menu-item > a, -.nav-mobile-strip__menu .current_page_item > a { - background: var(--color-primary); - color: var(--color-on-primary, #fff); -} - -@media (max-width: 767px) { - .nav-mobile-strip { - display: block; - } -} - -/* ============================================================ - * User avatar + dropdown - * ============================================================ */ -.nav-user { - position: relative; -} - -.nav-user__toggle { - width: 36px; - height: 36px; - border-radius: var(--radius-avatar); - padding: 0; - border: none; /* 对齐 zibll:头像无边框 */ - cursor: pointer; - /* Allow unread corner badge to paint outside the avatar circle. */ - overflow: visible; - background: var(--surface-2); - transition: box-shadow var(--dur-fast, 0.15s) var(--ease); -} - -.nav-user__toggle:hover { - box-shadow: 0 0 0 2px var(--color-primary-soft); -} - -.nav-user__toggle img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - border-radius: inherit; -} - -.user-dropdown { - position: absolute; - top: calc(100% + 8px); - right: 0; - width: 260px; - max-width: calc(100vw - 32px); - padding: 12px 0; - background: var(--surface-1); - border: 1px solid var(--color-line); - border-radius: var(--radius-lg, 8px); - box-shadow: var(--shadow-lg); - z-index: 1100; - opacity: 0; - visibility: hidden; - transform: translateY(-6px); - transition: opacity 0.2s, transform 0.2s, visibility 0.2s; -} - -.user-dropdown.is-open { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -.user-dropdown__profile { - display: flex; - align-items: center; - gap: 12px; - padding: 8px 16px 14px; -} - -.user-dropdown__profile img { - width: 44px; - height: 44px; - border-radius: var(--radius-avatar); - object-fit: cover; - flex-shrink: 0; -} - -.user-dropdown__name { - font-weight: 700; - font-size: 0.9375rem; - color: var(--color-ink); -} - -.user-dropdown__email { - font-size: 0.75rem; - color: var(--color-ink-4); - word-break: break-all; - margin-top: 2px; -} - -.user-dropdown__sep { - height: 1px; - background: var(--color-line); - margin: 6px 0; -} - -.user-dropdown a, -.user-dropdown button { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - padding: 0 16px; - height: 44px; - border: none; - background: none; - font-size: 0.875rem; - color: var(--color-ink); - text-align: left; - cursor: pointer; - transition: background var(--dur-fast, 0.15s) var(--ease), - color var(--dur-fast, 0.15s) var(--ease); -} - -.user-dropdown a:hover, -.user-dropdown button:hover { - background: var(--surface-3); - color: var(--color-primary-active); -} - -/* dropdown 项内的 SVG 图标 */ -.user-dropdown__item svg { - width: 16px; - height: 16px; - flex-shrink: 0; - opacity: 0.85; -} - -.user-dropdown__item span:first-of-type:not(.user-dropdown__pill) { - flex: 1; - min-width: 0; -} - -/* 未读消息数 badge */ -.user-dropdown__badge { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 18px; - height: 18px; - padding: 0 5px; - margin-left: auto; - font-size: 11px; - font-weight: 600; - color: #fff; - background: var(--color-error, #ef4444); - border-radius: 9px; - line-height: 1; -} - -.user-dropdown__credits { - display: flex; - align-items: center; - gap: 10px; - padding: 0 16px; - height: 44px; - font-size: 0.875rem; - color: var(--color-ink-2); -} - -.user-dropdown__credits i { - color: var(--color-warning); - flex-shrink: 0; -} - -.user-dropdown__credits-label { - flex: 1; -} - -.user-dropdown__credits-value { - font-weight: 600; - color: var(--color-primary); -} - -.user-dropdown__logout { - color: var(--color-error) !important; -} - -.user-dropdown__logout svg { - color: var(--color-error); -} - -.user-dropdown__logout:hover { - background: rgba(239, 68, 68, 0.08) !important; - color: var(--color-error) !important; -} - -.user-dropdown .badge-dot { - margin-left: auto; - min-width: 8px; - height: 8px; - border-radius: var(--radius-pill); - background: var(--color-error); -} - -/* ============================================================ - * Search panel - * ============================================================ */ -.nav-search-panel { - display: none; - padding: 12px 0 16px; - border-top: 1px solid var(--color-line); -} - -.nav-search-panel.is-open { - display: block; -} - -.nav-searchbox { - margin: 0; -} - -.nav-searchbox__field { - display: flex; - align-items: center; - gap: 10px; - min-height: 42px; - padding: 0 6px 0 14px; - border: 1px solid var(--color-line); - border-radius: var(--radius-pill, 999px); - background: var(--surface-3); - box-sizing: border-box; - transition: border-color var(--dur-fast, 0.15s) var(--ease), box-shadow var(--dur-fast, 0.15s) var(--ease), background var(--dur-fast, 0.15s) var(--ease); -} - -.nav-searchbox__icon { - order: 1; - flex: 0 0 16px; - width: 16px; - height: 16px; - color: var(--color-ink-4); - pointer-events: none; -} - -.nav-searchbox__input { - order: 2; - flex: 1; - min-width: 0; - width: auto; - height: 40px; - padding: 0; - border: 0; - background: transparent; - color: var(--color-ink); - font-size: 0.9rem; - line-height: 1.2; - box-sizing: border-box; -} - -.nav-searchbox__input:focus { - outline: none; -} - -.nav-searchbox__input::placeholder { - color: var(--color-ink-4); -} - -.nav-searchbox__submit { - order: 3; - flex: 0 0 auto; - height: 30px; - min-width: 64px; - padding: 0 14px; - border: 0; - border-radius: var(--radius-pill, 999px); - background: var(--color-primary); - color: #fff; - font-size: 0.8125rem; - font-weight: 600; - line-height: 1; - white-space: nowrap; - cursor: pointer; -} - -.nav-searchbox__field:focus-within { - border-color: var(--color-primary); - box-shadow: 0 0 0 3px var(--color-primary-soft); - background: var(--surface-1); -} - -.nav-searchbox__submit:hover { - background: var(--color-primary-active); -} - -/* ============================================================ - * Mobile drawer / mobile header - * ============================================================ */ -.mobile-header.nav-drawer-backdrop { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.45); - z-index: 1200; - opacity: 0; - visibility: hidden; - transition: opacity 0.3s ease, visibility 0.3s; -} - -.mobile-header.nav-drawer-backdrop.is-open { - opacity: 1; - visibility: visible; -} - -.mobile-header.nav-drawer { - position: fixed; - top: 0; - right: 0; - width: min(100vw, 360px); - height: 100vh; - max-height: 100dvh; - background: var(--surface-page); - z-index: 1210; - box-shadow: var(--shadow-drawer); - transform: translateX(100%); - transition: transform 0.32s var(--ease-out, ease); - display: flex; - flex-direction: column; - overflow: auto; - pointer-events: none; - visibility: hidden; -} - -.mobile-header.nav-drawer.is-open { - transform: translateX(0); - pointer-events: auto; - visibility: visible; -} - -.mobile-navbar { - display: flex; - flex-direction: column; - min-height: 100%; -} - -.mobile-navbar .navbar-brand { - max-width: calc(100% - 52px); - padding: 7px 0; -} - -.mobile-navbar .navbar-logo { - padding: 0; -} - -.nav-drawer-backdrop { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.45); - z-index: 1200; - opacity: 0; - visibility: hidden; - transition: opacity 0.3s ease, visibility 0.3s; -} - -.nav-drawer-backdrop.is-open { - opacity: 1; - visibility: visible; -} - -.nav-drawer { - position: fixed; - top: 0; - right: 0; - width: min(100vw, 360px); - height: 100vh; - max-height: 100dvh; - background: var(--surface-page); - z-index: 1210; - box-shadow: var(--shadow-drawer); - transform: translateX(100%); - transition: transform 0.32s var(--ease-out, ease); - display: flex; - flex-direction: column; - overflow: auto; - pointer-events: none; - visibility: hidden; -} - -.nav-drawer.is-open { - transform: translateX(0); - pointer-events: auto; - visibility: visible; -} - -.nav-drawer__head { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - padding: 16px 20px; - border-bottom: 1px solid var(--color-line); - font-weight: 700; - font-size: 1rem; -} - -.site-brand--drawer { - max-width: calc(100% - 52px); - padding: 7px 0; -} - -.site-brand--drawer .site-brand__media { - padding: 0; -} - -.nav-drawer__search { - padding: 16px 20px 0; -} - -.nav-drawer__search .nav-searchbox__field { - min-height: 40px; -} - -.nav-drawer__search .nav-searchbox__input { - height: 38px; -} - -.nav-drawer__search .nav-searchbox__submit { - height: 28px; - min-width: 58px; - padding: 0 12px; - font-size: 0.75rem; -} - -.nav-searchbox__meta { - display: grid; - gap: 10px; - margin-top: 12px; -} - -.nav-searchbox__types { - display: flex; - flex-wrap: wrap; - gap: 8px; -} - -.nav-searchbox__type { - display: inline-flex; - align-items: center; - min-height: 32px; - padding: 0 12px; - border: 1px solid var(--color-line); - border-radius: var(--radius-pill, 999px); - background: var(--surface-2); - color: var(--color-ink-3); - font-size: 0.8125rem; - font-weight: 600; - cursor: pointer; -} - -.nav-searchbox__type.is-active { - border-color: var(--color-primary); - background: var(--color-primary-soft); - color: var(--color-primary); -} - -.nav-searchbox__category-wrap { - position: relative; -} - -.nav-searchbox__category { - appearance: none; - width: 100%; - min-height: 36px; - padding: 0 34px 0 12px; - border: 1px solid var(--color-line); - border-radius: var(--radius-pill, 999px); - background: var(--surface-2); - color: var(--color-ink); - font: 500 0.875rem/1 var(--font-ui); -} - -.nav-searchbox__category-wrap::after { - content: ''; - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); - width: 0; - height: 0; - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-top: 5px solid var(--color-ink-3); - pointer-events: none; -} - -.nav-searchbox__category:disabled { - opacity: 0.56; - cursor: not-allowed; -} - -.nav-drawer__menu { - flex: 1; - padding: 16px 20px 32px; -} - -.nav-drawer__menu a { - display: block; - padding: 14px 0; - font-size: 1rem; - font-weight: 500; - color: var(--color-ink); - border-bottom: 1px solid var(--color-line-soft); -} - -.nav-drawer__menu a:hover { - color: var(--color-primary-active); -} - -.nav-drawer__menu ul { - list-style: none; - margin: 0; - padding: 0; -} - -.nav-drawer__auth { - padding: 20px; - display: flex; - flex-direction: column; - gap: 12px; - border-top: 1px solid var(--color-line); -} - -.nav-drawer__auth .btn-outline, -.nav-drawer__auth .btn-primary { - width: 100%; - height: 44px; -} - -.nav-drawer__publish { - padding: 0 20px 20px; -} - -.nav-drawer__publish .btn-primary { - width: 100%; - min-height: 44px; - justify-content: center; - gap: 8px; -} - - - -/* ============================================================ - * Header user box (Zibll-like sub-user-box grid) - * ============================================================ */ -.nav-user__toggle { - position: relative; -} -.nav-user__dot { - position: absolute; - top: -1px; - right: -1px; - width: 8px; - height: 8px; - border-radius: 50%; - background: var(--color-error, #ef4444); - border: 2px solid var(--surface-1, #fff); - box-sizing: content-box; - pointer-events: none; - z-index: 2; -} -.nav-user__guest-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - display: inline-flex; - align-items: center; - justify-content: center; - background: var(--surface-2); - color: var(--color-ink-3); -} -.user-dropdown { - width: 300px; - padding: 14px 12px 12px; -} -.user-dropdown__profile.user-info { - position: relative; - padding-right: 42px; -} -.user-dropdown__meta { - min-width: 0; - flex: 1; -} -.user-dropdown__name { - display: flex; - align-items: center; - gap: 6px; - flex-wrap: wrap; -} -/* Beat generic `.user-dropdown a { width:100%; height:44px }` sizing. */ -.user-dropdown a.user-dropdown__msg, -.user-dropdown__msg { - position: absolute; - top: 8px; - right: 8px; - width: 34px !important; - height: 34px !important; - min-width: 34px; - max-width: 34px; - border-radius: 50%; - display: inline-flex !important; - align-items: center; - justify-content: center; - gap: 0 !important; - padding: 0 !important; - background: var(--surface-2); - color: var(--color-ink-3); - box-sizing: border-box; -} -.user-dropdown a.user-dropdown__msg:hover, -.user-dropdown__msg:hover { - background: var(--surface-3); - color: var(--color-primary); -} -.user-dropdown__msg .user-dropdown__badge { - position: absolute; - top: -4px; - right: -4px; - margin: 0; -} -.user-dropdown__guest-title { - padding: 4px 8px 12px; - text-align: center; - font-weight: 700; - color: var(--color-ink); -} -.user-dropdown__actions { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 8px 4px; - padding: 4px 2px 2px; -} -.user-dropdown__actions--admin { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} -.user-dropdown__action { - display: flex !important; - flex-direction: column; - align-items: center; - justify-content: flex-start; - gap: 6px !important; - width: auto !important; - height: auto !important; - min-height: 0; - padding: 6px 4px !important; - text-align: center !important; - font-size: 12px !important; - line-height: 1.25; - color: var(--color-ink-3) !important; - background: transparent !important; -} -.user-dropdown__action:hover { - background: transparent !important; - color: var(--color-primary) !important; -} -.user-dropdown__action-icon { - width: 40px; - height: 40px; - border-radius: 50%; - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 15px; - color: #fff; -} -.user-dropdown__action-icon.is-blue { background: linear-gradient(135deg, #60a5fa, #3b82f6); } -.user-dropdown__action-icon.is-purple { background: linear-gradient(135deg, #a78bfa, #8b5cf6); } -.user-dropdown__action-icon.is-green { background: linear-gradient(135deg, #34d399, #10b981); } -.user-dropdown__action-icon.is-red { background: linear-gradient(135deg, #f87171, #ef4444); } -.user-dropdown__action-icon.is-yellow { background: linear-gradient(135deg, #fbbf24, #f59e0b); color: #1f2937; } -.user-dropdown__action.is-danger { - color: var(--color-error, #ef4444) !important; -} -.user-dropdown__credits { - margin-top: 2px; - border-radius: 12px; - background: var(--surface-2); - margin-left: 4px; - margin-right: 4px; - width: auto; -} diff --git a/assets/css/frontend/nav/nav-fixed-mobile-fallback.css b/assets/css/frontend/nav/nav-fixed-mobile-fallback.css deleted file mode 100644 index 9490453e..00000000 --- a/assets/css/frontend/nav/nav-fixed-mobile-fallback.css +++ /dev/null @@ -1,10 +0,0 @@ -/* ===== nav_fixed mobile fallback ===== */ -/* On mobile, static nav should remain sticky so the hamburger toggle stays accessible */ -@media (max-width: 767px) { - .has-static-nav .site-nav--static { - position: sticky; - top: 0; - z-index: 1000; - } -} - diff --git a/assets/css/frontend/nav/responsive-mega-menu.css b/assets/css/frontend/nav/responsive-mega-menu.css deleted file mode 100644 index 55a61fe1..00000000 --- a/assets/css/frontend/nav/responsive-mega-menu.css +++ /dev/null @@ -1,109 +0,0 @@ -/* Responsive Mega Menu */ -@media (max-width: 767px) { - ul.nav-desktop .mega-menu-item > .mega-menu__panel { - position: static; - transform: none; - width: 100%; - max-width: none; - margin: 0; - box-shadow: none; - } - - .mega-menu__columns-2, - .mega-menu__columns-3, - .mega-menu__columns-4, - .mega-menu__columns-5 { - grid-template-columns: 1fr; - } -} - -/* ============================================================ - * Right actions (icons + auth) - * ============================================================ */ -.nav-actions { - display: flex; - align-items: center; - gap: 4px; - flex-shrink: 0; - margin-left: auto; - overflow: visible; - position: relative; - z-index: 25; -} - -.nav-settings-link, -.nav-publish-btn { - flex-shrink: 0; -} - -.nav-settings-link svg { - width: 18px; - height: 18px; -} - -.nav-publish-btn { - display: inline-flex; - align-items: center; - gap: 8px; - height: 36px; - padding: 0 14px; - font-size: 0.875rem; - font-weight: 600; -} - -.nav-publish-btn i { - font-size: 0.8125rem; -} - -.theme-toggle.is-animating svg { - transform: rotate(360deg); -} - -/* ============================================================ - * Auth buttons (in nav, when logged out) - * ============================================================ */ -.nav-auth { - display: none; - align-items: center; - gap: 8px; -} - -/* btn-outline / btn-primary 复用 core/buttons.css 的定义, - * 这里仅做导航专用调整(高度对齐、字体) */ -.nav-auth .btn-outline, -.nav-auth .btn-primary { - height: 36px; - font-size: 0.875rem; - padding: 0 16px; -} - -/* Auth dropdown variant (layouts 1/3) — icon trigger + panel */ -.nav-auth-dropdown { - position: relative; - display: none; - align-items: center; -} - -.nav-auth-dropdown__trigger { - width: 36px; - height: 36px; -} - -.nav-auth-dropdown__trigger svg { - width: 20px; - height: 20px; -} - -.nav-auth-dropdown__panel { - display: none; - position: absolute; - top: calc(100% + 8px); - right: 0; - min-width: 180px; - z-index: 1100; -} - -.nav-auth-dropdown.is-open .nav-auth-dropdown__panel { - display: block; -} - diff --git a/assets/css/frontend/nav/zib-utilities.css b/assets/css/frontend/nav/zib-utilities.css new file mode 100644 index 00000000..2f2ed681 --- /dev/null +++ b/assets/css/frontend/nav/zib-utilities.css @@ -0,0 +1,132 @@ +/* Utilities for zibll header chrome */ +.css-icon.i-menu { + position: relative; + display: inline-block; + width: 1.15em; + height: 1em; + vertical-align: -0.1em; +} +.css-icon.i-menu > i, +.css-icon.i-menu::before, +.css-icon.i-menu::after { + content: ""; + position: absolute; + left: 0; + right: 0; + height: 2px; + background: currentColor; + border-radius: 1px; + transition: 0.25s; +} +.css-icon.i-menu > i { top: 50%; margin-top: -1px; } +.css-icon.i-menu::before { top: 0; } +.css-icon.i-menu::after { bottom: 0; } + +.list-inline { padding-left: 0; list-style: none; margin: 0; } +.list-inline > li { display: inline-block; vertical-align: middle; } +.list-inline.splitters > li + li { margin-left: 6px; } + +.navbar-top .flex.ac { display: flex; align-items: center; } +.navbar-top .flex.jsb { display: flex; justify-content: space-between; } +.navbar-top .flex.jsa { display: flex; justify-content: space-around; } +.navbar-top .flex.jc { display: flex; justify-content: center; } +.mb6 { margin-bottom: 6px; } +.mb10 { margin-bottom: 10px; } +.mb20 { margin-bottom: 20px; } +.mt6 { margin-top: 6px; } +.mt10 { margin-top: 10px; } +.ml6 { margin-left: 6px; } +.ml10 { margin-left: 10px; } +.em09 { font-size: 0.9em; } +.em12 { font-size: 1.2em; } +.muted-2-color { opacity: 0.7; } +.muted-3-color { opacity: 0.55; } +.text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.padding-10 { padding: 10px; } +.relative { position: relative; } +.inline-block { display: inline-block; } +.hide { display: none !important; } +.pull-right { float: right; } +.null { background: none; border: 0; padding: 0; color: inherit; } +.abs-right { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); } + +/* Mid breakpoint fold trigger (zibll ~991) */ +@media (max-width: 991px) { + .navbar-top .show-nav-but { display: block !important; } + .navbar-top .nav.navbar-nav:not(.show) { + display: none; + } + .navbar-top .nav.navbar-nav.show { + display: block; + position: absolute; + left: 0; right: 0; + top: 100%; + background: var(--main-bg-color, #fff); + z-index: 1001; + padding: 10px; + box-shadow: 0 8px 20px rgba(0,0,0,.08); + } +} + +/* Language dropdown */ +.language-dropdown { position: relative; } +.language-dropdown .dropdown-menu, +.language-dropdown .hover-show-con { + min-width: 140px; + right: 0; + left: auto; + padding: 8px 0; +} +.language-dropdown .translate-button { display: flex; align-items: center; padding: 6px 14px; } +.language-dropdown .translate-button.active { color: var(--focus-color); } + +/* Layout2 inline search focus panel */ +.navbar-collapse .search-input { + min-width: 160px; + max-width: 240px; + height: 34px; + border-radius: 20px; + border: 0; + padding: 0 36px 0 14px; +} +.navbar-form.navbar-left.hover-show { margin: 0 8px; } +.navbar-form .form-group.relative { position: relative; } +.navbar-form .abs-right { right: 10px; } + +/* Mobile drawer body scroll lock */ +body.mobile-navbar-show { overflow: hidden; } + +/* Ensure container-header flex row */ +.container-header { + display: flex; + align-items: center; + flex-wrap: nowrap; + max-width: var(--nav-max-width, 100%); + margin: 0 auto; + width: 100%; +} +.navbar-collapse { + display: flex; + align-items: center; + flex: 1; + min-width: 0; + flex-wrap: nowrap; +} +.navbar-header { display: flex; align-items: center; flex-shrink: 0; } +.navbar-top .navbar-toggle { display: none; background: none; border: 0; color: inherit; } +@media (max-width: 767px) { + .navbar-top .navbar-toggle { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; } + .navbar-collapse { display: none; } +} + +/* Senior submenu full width under fixed header */ +.navbar-top .sub-menu.senior-submenu { + position: fixed; + left: 0; right: 0; + top: 59px; + width: 100%; + min-width: 100%; + padding: 20px 0; + border-radius: 0; + z-index: 998; +} diff --git a/assets/js/core/nav.js b/assets/js/core/nav.js index 86c3d09a..b773f568 100644 --- a/assets/js/core/nav.js +++ b/assets/js/core/nav.js @@ -1,13 +1,15 @@ /** - * AKSRT nav chrome — zibll contract (body.mobile-navbar-show, folding, chevron). - * Drawer open/close is handled by aksrt-runtime [data-toggle-class]. + * AKSRT nav chrome — zibll contract (folding, chevron, language, drawer a11y). + * Drawer open/close via aksrt-runtime [data-toggle-class] → body.mobile-navbar-show. */ (function () { "use strict"; - function appendChevrons() { - document.querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) { - if (a.querySelector(".fa-angle-down")) return; + var foldTimer = null; + + function appendChevrons(root) { + (root || document).querySelectorAll(".navbar-top li.menu-item-has-children > a").forEach(function (a) { + if (a.querySelector(".fa-angle-down, .fas.fa-angle-down")) return; var i = document.createElement("i"); i.className = "fa fa-angle-down ml6"; i.setAttribute("aria-hidden", "true"); @@ -15,18 +17,30 @@ }); } + function clearFolding() { + var more = document.querySelector(".navbar-nav > li.aksrt-nav-more"); + if (!more) return; + var sub = more.querySelector(".sub-menu"); + var nav = more.parentNode; + if (sub && nav) { + while (sub.firstChild) { + nav.insertBefore(sub.firstChild, more); + } + } + more.remove(); + } + function navFolding() { var collapse = document.querySelector(".navbar-collapse"); var nav = document.querySelector(".navbar-nav"); if (!collapse || !nav) return; - if (window.innerWidth <= 996) return; + clearFolding(); + + if (window.innerWidth <= 996) return; var header = document.querySelector(".header"); if (header && header.offsetHeight <= 81) return; - // Already folded? - if (nav.querySelector("li.aksrt-nav-more")) return; - var surplus = collapse.clientWidth; Array.prototype.forEach.call(collapse.children, function (child) { if (!child.classList.contains("navbar-nav")) { @@ -40,9 +54,7 @@ var foldItems = []; Array.prototype.forEach.call(nav.children, function (li) { navsWidth += li.offsetWidth || 0; - if (navsWidth > surplus) { - foldItems.push(li); - } + if (navsWidth > surplus) foldItems.push(li); }); if (!foldItems.length) return; @@ -51,14 +63,33 @@ more.innerHTML = '
'; var sub = more.querySelector(".sub-menu"); - foldItems.forEach(function (li) { - sub.appendChild(li); - }); + foldItems.forEach(function (li) { sub.appendChild(li); }); nav.appendChild(more); + appendChevrons(more); + } + + function scheduleFold() { + if (foldTimer) clearTimeout(foldTimer); + foldTimer = setTimeout(function () { + try { navFolding(); } catch (e) {} + }, 80); + } + + function bindLanguage() { + document.addEventListener("click", function (e) { + var btn = e.target && e.target.closest ? e.target.closest(".translate-button[data-language]") : null; + if (!btn) return; + e.preventDefault(); + var lang = btn.getAttribute("data-language"); + if (!lang) return; + try { localStorage.setItem("aksrt_lang", lang); } catch (err) {} + var url = new URL(window.location.href); + url.searchParams.set("lang", lang); + window.location.href = url.toString(); + }); } function bindDrawerA11y() { - // Esc closes mobile nav via body class. document.addEventListener("keydown", function (e) { if (e.key === "Escape" && document.body.classList.contains("mobile-navbar-show")) { document.body.classList.remove("mobile-navbar-show"); @@ -68,18 +99,14 @@ function init() { appendChevrons(); - try { - navFolding(); - } catch (err) { - // ignore fold failures - } + scheduleFold(); + bindLanguage(); bindDrawerA11y(); + window.addEventListener("resize", scheduleFold, { passive: true }); } if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") { - window.AksrtFrontend.register("aksrt-nav-chrome", function () { - init(); - }); + window.AksrtFrontend.register("aksrt-nav-chrome", function () { init(); }); } else if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { diff --git a/assets/js/section-navs.js b/assets/js/section-navs.js index ad70ed9f..d34e283a 100644 --- a/assets/js/section-navs.js +++ b/assets/js/section-navs.js @@ -1,9 +1,7 @@ /** - * AKSRT Section Navs — Article TOC / Scrollspy + * AKSRT Section Navs — zibll section_navs parity (posts-nav-lists + scrollspy). * - * Auto-generates a table of contents from h1~h4 headings within - * [data-nav] content areas. Scrollspy highlights the current section. - * Collapsible sub-items when the TOC is tall. + * Builds TOC from [data-nav] h1–h4 into .posts-nav-box / .posts-nav-lists. * * @package AKSRT */ @@ -12,164 +10,138 @@ var HEADING_SEL = 'h1, h2, h3, h4'; var MIN_HEADINGS = 2; - var SCROLL_OFFSET = 105; - var MAX_HEIGHT_COLLAPSE = 380; + var NAVBOX = '.posts-nav-box'; + var NAV_CLASS = 'posts-nav-lists'; - function initSectionNavs() { - var navContainer = document.querySelector('[data-nav]'); - if (!navContainer) return; + function isExcluded(el) { + return el.classList.contains('item-heading') || !!el.closest('.no-nav'); + } - // Single-post TOC is owned by page-template.js (.posts-nav-box .toc-list). - // Do not invent a second .aksrt-section-nav tree on article singles. - if (document.querySelector('.posts-nav-box .toc-list, .posts-nav-box.toc-widget')) { + function ensureId(el, index) { + if (!el.id) { + el.id = 'section-nav-' + index; + } + return el.id; + } + + function buildLists(root) { + var headings = root.querySelectorAll(HEADING_SEL); + var html = ''; + var count = 0; + headings.forEach(function (h, i) { + if (isExcluded(h)) return; + var id = ensureId(h, i); + var tag = h.tagName.toUpperCase(); + var text = (h.textContent || '').trim(); + if (!text) return; + html += '- +
+
+
+
+
+
+