fix: refine global topbar integration

This commit is contained in:
2026-06-26 11:16:17 +02:00
parent 93a3f9fc0d
commit 40d431023a
4 changed files with 23 additions and 135 deletions
-41
View File
@@ -153,23 +153,6 @@
return document.querySelector('[data-wg-topbar]'); return document.querySelector('[data-wg-topbar]');
} }
function closeWestgateTopbarPanels(topbar, exceptKey) {
if (!topbar || typeof topbar.querySelectorAll !== 'function') {
return;
}
toArray(topbar.querySelectorAll('[data-wg-panel]')).forEach((panel) => {
if (panel.getAttribute('data-wg-panel') !== exceptKey) {
panel.classList.remove('is-open');
}
});
toArray(topbar.querySelectorAll('[data-wg-menu]')).forEach((trigger) => {
if (trigger.getAttribute('data-wg-menu') !== exceptKey) {
trigger.setAttribute('aria-expanded', 'false');
}
});
}
function closeWestgateTopbarDrawer(topbar) { function closeWestgateTopbarDrawer(topbar) {
if (!topbar) { if (!topbar) {
return; return;
@@ -195,22 +178,6 @@
return; return;
} }
const trigger = event.target.closest && event.target.closest('[data-wg-menu]');
if (trigger && currentTopbar.contains(trigger)) {
event.preventDefault();
event.stopPropagation();
const key = trigger.getAttribute('data-wg-menu');
const panel = currentTopbar.querySelector(`[data-wg-panel="${key}"]`);
const shouldOpen = !!panel && !panel.classList.contains('is-open');
closeWestgateTopbarPanels(currentTopbar, shouldOpen ? key : null);
if (panel) {
panel.classList.toggle('is-open', shouldOpen);
}
trigger.setAttribute('aria-expanded', String(shouldOpen));
return;
}
const burger = event.target.closest && event.target.closest('[data-wg-burger]'); const burger = event.target.closest && event.target.closest('[data-wg-burger]');
if (burger && currentTopbar.contains(burger)) { if (burger && currentTopbar.contains(burger)) {
event.preventDefault(); event.preventDefault();
@@ -219,15 +186,9 @@
const isOpen = !currentTopbar.classList.contains('is-drawer-open'); const isOpen = !currentTopbar.classList.contains('is-drawer-open');
currentTopbar.classList.toggle('is-drawer-open', isOpen); currentTopbar.classList.toggle('is-drawer-open', isOpen);
burger.setAttribute('aria-expanded', String(isOpen)); burger.setAttribute('aria-expanded', String(isOpen));
closeWestgateTopbarPanels(currentTopbar, null);
return; return;
} }
if (event.target.closest && event.target.closest('[data-wg-panel]')) {
return;
}
closeWestgateTopbarPanels(currentTopbar, null);
if (!currentTopbar.contains(event.target)) { if (!currentTopbar.contains(event.target)) {
closeWestgateTopbarDrawer(currentTopbar); closeWestgateTopbarDrawer(currentTopbar);
} }
@@ -239,7 +200,6 @@
} }
const currentTopbar = getWestgateTopbar(); const currentTopbar = getWestgateTopbar();
closeWestgateTopbarPanels(currentTopbar, null);
closeWestgateTopbarDrawer(currentTopbar); closeWestgateTopbarDrawer(currentTopbar);
}); });
@@ -263,7 +223,6 @@
$(window).on('action:ajaxify.end', function () { $(window).on('action:ajaxify.end', function () {
wrapWestgateWikiTables(document); wrapWestgateWikiTables(document);
initWestgateTopbar(); initWestgateTopbar();
closeWestgateTopbarPanels(getWestgateTopbar(), null);
closeWestgateTopbarDrawer(getWestgateTopbar()); closeWestgateTopbarDrawer(getWestgateTopbar());
}); });
+14 -75
View File
@@ -1,3 +1,11 @@
$wg-topbar-panel-bg: linear-gradient(
100deg,
#2a1222 0%,
#19161f 23%,
#121017 62%,
#0d0c11 100%
);
.wg-layout-container { .wg-layout-container {
min-height: 100vh; min-height: 100vh;
} }
@@ -17,7 +25,7 @@
.wg-topbar__inner { .wg-topbar__inner {
display: grid; display: grid;
grid-template-columns: auto minmax(0, 1fr) auto auto; grid-template-columns: auto minmax(0, 1fr) auto;
align-items: center; align-items: center;
gap: 0.9rem; gap: 0.9rem;
width: min(100%, 1420px); width: min(100%, 1420px);
@@ -60,35 +68,16 @@
font-weight: 700; font-weight: 700;
} }
.wg-topbar__brand-text {
display: flex;
flex-direction: column;
min-width: 0;
line-height: 1;
}
.wg-topbar__brand-name { .wg-topbar__brand-name {
max-width: 22ch;
overflow: hidden;
color: var(--wg-text); color: var(--wg-text);
font-family: var(--wg-font-display); font-family: var(--wg-font-display);
font-size: 0.96rem; font-size: 0.96rem;
font-weight: 600; font-weight: 600;
letter-spacing: 0.08em; letter-spacing: 0.08em;
text-overflow: ellipsis;
text-transform: uppercase; text-transform: uppercase;
white-space: nowrap; white-space: nowrap;
} }
.wg-topbar__brand-subtitle {
margin-top: 0.28rem;
color: var(--wg-gold-soft);
font-family: var(--wg-font-code);
font-size: 0.62rem;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.wg-topbar__nav { .wg-topbar__nav {
min-width: 0; min-width: 0;
} }
@@ -104,8 +93,7 @@
} }
.wg-topbar .nav-link, .wg-topbar .nav-link,
.wg-topbar__nav-link, .wg-topbar__nav-link {
.wg-topbar__forums-toggle {
min-height: 2.35rem; min-height: 2.35rem;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 6px; border-radius: 6px;
@@ -122,8 +110,6 @@
.wg-topbar .nav-link:focus, .wg-topbar .nav-link:focus,
.wg-topbar__nav-link:hover, .wg-topbar__nav-link:hover,
.wg-topbar__nav-link:focus, .wg-topbar__nav-link:focus,
.wg-topbar__forums-toggle:hover,
.wg-topbar__forums-toggle:focus,
.wg-topbar .nav-item.active > .nav-link, .wg-topbar .nav-item.active > .nav-link,
.wg-topbar .nav-item.active > .navigation-link { .wg-topbar .nav-item.active > .navigation-link {
color: #f3ede4; color: #f3ede4;
@@ -132,16 +118,6 @@
box-shadow: inset 0 1px 0 rgba(255, 244, 221, 0.035); box-shadow: inset 0 1px 0 rgba(255, 244, 221, 0.035);
} }
.wg-topbar__forums {
position: relative;
}
.wg-topbar__forums-toggle {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.wg-topbar__utilities { .wg-topbar__utilities {
justify-self: end; justify-self: end;
} }
@@ -187,8 +163,7 @@
.wg-topbar .notifications-dropdown, .wg-topbar .notifications-dropdown,
.wg-topbar .chats-dropdown, .wg-topbar .chats-dropdown,
.wg-topbar .drafts-dropdown, .wg-topbar .drafts-dropdown,
.wg-topbar .user-dropdown, .wg-topbar .user-dropdown {
.wg-topbar__panel {
min-width: min(22rem, calc(100vw - 1.5rem)); min-width: min(22rem, calc(100vw - 1.5rem));
max-width: calc(100vw - 1.5rem); max-width: calc(100vw - 1.5rem);
border: 1px solid rgba(194, 163, 90, 0.22) !important; border: 1px solid rgba(194, 163, 90, 0.22) !important;
@@ -196,7 +171,7 @@
color: var(--wg-text-soft) !important; color: var(--wg-text-soft) !important;
background: background:
linear-gradient(180deg, rgba(255, 244, 221, 0.028), transparent 36%), linear-gradient(180deg, rgba(255, 244, 221, 0.028), transparent 36%),
var(--wg-velvet-panel) !important; $wg-topbar-panel-bg !important;
box-shadow: box-shadow:
inset 0 1px 0 rgba(255, 244, 221, 0.035), inset 0 1px 0 rgba(255, 244, 221, 0.035),
0 18px 42px rgba(0, 0, 0, 0.42) !important; 0 18px 42px rgba(0, 0, 0, 0.42) !important;
@@ -258,36 +233,6 @@
background: rgba(194, 163, 90, 0.1); background: rgba(194, 163, 90, 0.1);
} }
.wg-topbar__panel {
position: absolute;
top: calc(100% + 0.45rem);
right: 0;
display: none;
padding: 0.42rem;
}
.wg-topbar__panel.is-open {
display: grid;
gap: 0.2rem;
}
.wg-topbar__panel--forums a {
display: flex;
align-items: center;
min-height: 2.25rem;
border-radius: 6px;
padding: 0.35rem 0.55rem;
color: var(--wg-text-soft);
font-size: 0.9rem;
text-decoration: none;
}
.wg-topbar__panel--forums a:hover,
.wg-topbar__panel--forums a:focus {
color: var(--wg-text);
background: rgba(194, 163, 90, 0.08);
}
.wg-topbar__burger { .wg-topbar__burger {
display: none; display: none;
align-items: center; align-items: center;
@@ -310,7 +255,8 @@
display: none; display: none;
border-top: 1px solid rgba(194, 163, 90, 0.12); border-top: 1px solid rgba(194, 163, 90, 0.12);
background: background:
linear-gradient(180deg, rgba(42, 18, 34, 0.98), rgba(12, 10, 15, 0.99)); linear-gradient(180deg, rgba(255, 244, 221, 0.025), transparent 38%),
$wg-topbar-panel-bg;
} }
.wg-topbar.is-drawer-open .wg-topbar__drawer { .wg-topbar.is-drawer-open .wg-topbar__drawer {
@@ -389,12 +335,6 @@
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto;
} }
.wg-topbar__brand-name {
max-width: 16ch;
}
.wg-topbar__brand-subtitle,
.wg-topbar__forums,
.wg-topbar__utilities { .wg-topbar__utilities {
display: none; display: none;
} }
@@ -411,7 +351,6 @@
} }
.wg-topbar__brand-name { .wg-topbar__brand-name {
max-width: 13ch;
font-size: 0.82rem; font-size: 0.82rem;
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
+2 -19
View File
@@ -1,11 +1,8 @@
<header class="wg-topbar sticky-top" data-wg-topbar> <header class="wg-topbar sticky-top" data-wg-topbar>
<div class="wg-topbar__inner"> <div class="wg-topbar__inner">
<a class="wg-topbar__brand" href="{relative_path}/" aria-label="{config.siteTitle}"> <a class="wg-topbar__brand" href="{relative_path}/" aria-label="SHADOWS OVER WESTGATE">
<span class="wg-topbar__brand-mark" aria-hidden="true">W</span> <span class="wg-topbar__brand-mark" aria-hidden="true">W</span>
<span class="wg-topbar__brand-text"> <span class="wg-topbar__brand-name">SHADOWS OVER WESTGATE</span>
<span class="wg-topbar__brand-name">{config.siteTitle}</span>
<span class="wg-topbar__brand-subtitle">Shadows Over Westgate</span>
</span>
</a> </a>
<nav class="wg-topbar__nav" aria-label="[[global:navigation]]"> <nav class="wg-topbar__nav" aria-label="[[global:navigation]]">
@@ -31,20 +28,6 @@
</ul> </ul>
</nav> </nav>
<div class="wg-topbar__forums dropdown">
<button class="wg-topbar__nav-link wg-topbar__forums-toggle" type="button" data-wg-menu="forums" aria-expanded="false" aria-haspopup="true">
<span>Forums</span>
<i class="fa fa-fw fa-chevron-down" aria-hidden="true"></i>
</button>
<div class="wg-topbar__panel wg-topbar__panel--forums" data-wg-panel="forums" role="menu">
<a href="{relative_path}/categories" role="menuitem">[[pages:categories]]</a>
<a href="{relative_path}/recent" role="menuitem">[[recent:title]]</a>
<a href="{relative_path}/unread" role="menuitem">[[unread:title]]</a>
<a href="{relative_path}/popular" role="menuitem">[[pages:popular]]</a>
<a href="{relative_path}/tags" role="menuitem">[[tags:tags]]</a>
</div>
</div>
<div class="wg-topbar__utilities"> <div class="wg-topbar__utilities">
{{{ if config.loggedIn }}} {{{ if config.loggedIn }}}
<ul id="wg-topbar-logged-in-menu" class="wg-topbar__utility-list list-unstyled d-flex align-items-center mb-0"> <ul id="wg-topbar-logged-in-menu" class="wg-topbar__utility-list list-unstyled d-flex align-items-center mb-0">
+7
View File
@@ -107,6 +107,13 @@ assertIncludes(topbar, '{{{ if allowRegistration }}}', 'Registration should rema
assertIncludes(topbar, '{{{ each navigation }}}', 'Topbar should render ACP Navigation items'); assertIncludes(topbar, '{{{ each navigation }}}', 'Topbar should render ACP Navigation items');
assertIncludes(topbar, '{./textClass}', 'Topbar should honor ACP Navigation text visibility classes'); assertIncludes(topbar, '{./textClass}', 'Topbar should honor ACP Navigation text visibility classes');
assertExcludes(topbar, 'href="{relative_path}/admin"', 'Topbar should not hard-code the administrator link'); assertExcludes(topbar, 'href="{relative_path}/admin"', 'Topbar should not hard-code the administrator link');
assertIncludes(topbar, 'SHADOWS OVER WESTGATE', 'Topbar brand should use the single required identity line');
assertExcludes(topbar, 'wg-topbar__brand-subtitle', 'Topbar should not repeat the site name as a subtitle');
assertExcludes(topbar, 'wg-topbar__forums', 'Topbar should not ship a separate desktop Forums dropdown');
assertExcludes(topbar, 'data-wg-menu="forums"', 'Forums should not use a custom topbar menu trigger');
assertIncludes(stylesheet, '$wg-topbar-panel-bg', 'Topbar menu surfaces should use an opaque local panel base');
assertExcludes(stylesheet, 'var(--wg-velvet-panel) !important;', 'Topbar menu surfaces should not inherit the translucent velvet panel token');
assertExcludes(stylesheet, 'text-overflow: ellipsis;', 'Topbar brand should not truncate in normal desktop layouts');
assertMissing( assertMissing(
'templates/partials/header/brand.tpl', 'templates/partials/header/brand.tpl',