Mirrors the existing unread-drawer pattern: a new dropdown next to the notification bell, gated on templateData.support.visible (injected by the support plugin's filter:middleware.renderHeader hook, on every page render, for viewers with any support access at all). Opening it fetches GET /plugins/support/notifications via the api module, renders up to 10 entries by textContent (never innerHTML), and marks everything read via POST .../notifications/read, clearing the badge client-side. Also present in the mobile burger drawer, same gating. ponytail: no live socket push for this badge (core's own unread/notification counts get one); it only catches up on the next full page load after the box is opened. Noted in client.js as the upgrade path if that gap matters. Verified live against sow-nodebb-plugin-support's dev NodeBB stack (theme + plugin both mounted): icon hidden for a user with no support access, badge count and dropdown contents correct for a reviewer, badge clears on open. Full plain-node test suite passes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
388 lines
8.5 KiB
SCSS
388 lines
8.5 KiB
SCSS
$wg-topbar-panel-bg: rgba(21, 17, 26, 0.98);
|
|
|
|
.wg-layout-container {
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.wg-topbar {
|
|
top: 0;
|
|
z-index: 1020;
|
|
color: var(--wg-text-soft);
|
|
background: rgb(24, 20, 29);
|
|
border-bottom: 1px solid rgba(194, 163, 90, 0.2);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 244, 221, 0.04),
|
|
0 12px 32px rgba(0, 0, 0, 0.34);
|
|
}
|
|
|
|
.wg-topbar__inner {
|
|
display: grid;
|
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
align-items: center;
|
|
gap: 0.9rem;
|
|
width: min(100%, var(--wg-page-width));
|
|
min-height: 64px;
|
|
margin: 0 auto;
|
|
padding: 0.55rem clamp(0.85rem, 2vw, 1.5rem);
|
|
}
|
|
|
|
.wg-topbar__brand {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-width: 0;
|
|
gap: 0.7rem;
|
|
color: var(--wg-text);
|
|
text-decoration: none;
|
|
|
|
&:hover,
|
|
&:focus {
|
|
color: #f3ede4;
|
|
text-decoration: none;
|
|
}
|
|
}
|
|
|
|
.wg-topbar__brand-mark {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 2.3rem;
|
|
height: 2.3rem;
|
|
border: 1px solid rgba(194, 163, 90, 0.36);
|
|
border-radius: 50%;
|
|
color: var(--wg-gold);
|
|
background:
|
|
radial-gradient(circle at 38% 24%, rgba(255, 238, 190, 0.2), transparent 30%),
|
|
linear-gradient(145deg, rgba(58, 24, 48, 0.7), rgba(10, 9, 13, 0.98));
|
|
box-shadow:
|
|
inset 0 0 0 1px rgba(9, 8, 11, 0.66),
|
|
0 8px 18px rgba(0, 0, 0, 0.35);
|
|
font-family: var(--wg-font-display);
|
|
font-weight: 700;
|
|
}
|
|
|
|
.wg-topbar__brand-name {
|
|
color: var(--wg-text);
|
|
font-family: var(--wg-font-display);
|
|
font-size: 0.96rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.wg-topbar__nav {
|
|
min-width: 0;
|
|
}
|
|
|
|
.wg-topbar__nav-list,
|
|
.wg-topbar__utility-list {
|
|
gap: 0.28rem;
|
|
}
|
|
|
|
.wg-topbar__nav-list {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wg-topbar .nav-link,
|
|
.wg-topbar__nav-link {
|
|
min-height: 2.35rem;
|
|
border: 1px solid transparent;
|
|
border-radius: 6px;
|
|
padding: 0.42rem 0.62rem;
|
|
color: var(--wg-text-soft);
|
|
background: transparent;
|
|
font-family: var(--wg-font-ui);
|
|
font-size: 0.86rem;
|
|
line-height: 1.1;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.wg-topbar .nav-link:hover,
|
|
.wg-topbar .nav-link:focus,
|
|
.wg-topbar__nav-link:hover,
|
|
.wg-topbar__nav-link:focus,
|
|
.wg-topbar .nav-item.active > .nav-link,
|
|
.wg-topbar .nav-item.active > .navigation-link {
|
|
color: #f3ede4;
|
|
border-color: rgba(194, 163, 90, 0.2);
|
|
background: rgba(194, 163, 90, 0.075);
|
|
box-shadow: inset 0 1px 0 rgba(255, 244, 221, 0.035);
|
|
}
|
|
|
|
.wg-topbar__utilities {
|
|
justify-self: end;
|
|
}
|
|
|
|
.wg-topbar__utility-list {
|
|
align-items: center;
|
|
}
|
|
|
|
.wg-topbar__utility-list > .nav-item {
|
|
position: relative;
|
|
}
|
|
|
|
.wg-topbar__utility-list :where(.nav-text, .visible-open) {
|
|
display: none !important;
|
|
}
|
|
|
|
.wg-topbar__utility-list .nav-link {
|
|
// beat Bootstrap's !important .justify-content-between on notifications/chats/drafts links
|
|
justify-content: center !important;
|
|
width: 2.35rem;
|
|
height: 2.35rem;
|
|
padding: 0;
|
|
}
|
|
|
|
.wg-topbar__utility-list [component$="/count"],
|
|
.wg-topbar__drawer-actions [component$="/count"],
|
|
.wg-topbar [component="navigation/count"] {
|
|
background: linear-gradient(to bottom, rgba(142, 52, 56, 0.92), rgba(84, 28, 39, 0.96)) !important;
|
|
border: 1px solid rgba(216, 194, 138, 0.26);
|
|
color: #fff0dc;
|
|
}
|
|
|
|
.wg-topbar__utility-list .visible-closed:not(.hidden) {
|
|
display: inline-block !important;
|
|
}
|
|
|
|
.wg-topbar__skin .dropend {
|
|
margin: 0 !important;
|
|
}
|
|
|
|
.wg-topbar__skin .dropdown-menu,
|
|
.wg-topbar__dropdown,
|
|
.wg-topbar .search-dropdown,
|
|
.wg-topbar .notifications-dropdown,
|
|
.wg-topbar .chats-dropdown,
|
|
.wg-topbar .drafts-dropdown,
|
|
.wg-topbar .user-dropdown {
|
|
min-width: min(22rem, calc(100vw - 1.5rem));
|
|
max-width: calc(100vw - 1.5rem);
|
|
border: 1px solid rgba(194, 163, 90, 0.22) !important;
|
|
border-radius: 8px !important;
|
|
color: var(--wg-text-soft) !important;
|
|
background:
|
|
linear-gradient(180deg, rgba(255, 244, 221, 0.028), transparent 36%),
|
|
$wg-topbar-panel-bg !important;
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 244, 221, 0.035),
|
|
0 18px 42px rgba(0, 0, 0, 0.42) !important;
|
|
}
|
|
|
|
.wg-topbar .notifications-dropdown,
|
|
.wg-topbar .chats-dropdown,
|
|
.wg-topbar .drafts-dropdown,
|
|
.wg-topbar .unread-dropdown,
|
|
.wg-topbar .support-dropdown {
|
|
width: min(24rem, calc(100vw - 1.5rem));
|
|
}
|
|
|
|
.wg-topbar .wg-unread-item {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.wg-topbar .wg-unread-item__category {
|
|
margin-left: auto;
|
|
flex-shrink: 0;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.wg-topbar .wg-support-item--unread {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.wg-topbar .dropdown-item,
|
|
.wg-topbar .btn.btn-ghost,
|
|
.wg-topbar .btn.btn-light {
|
|
color: var(--wg-text-soft) !important;
|
|
}
|
|
|
|
.wg-topbar .dropdown-item:hover,
|
|
.wg-topbar .dropdown-item:focus,
|
|
.wg-topbar .btn.btn-ghost:hover,
|
|
.wg-topbar .btn.btn-ghost:focus,
|
|
.wg-topbar .btn.btn-light:hover,
|
|
.wg-topbar .btn.btn-light:focus {
|
|
color: var(--wg-text) !important;
|
|
background: var(--wg-border-soft) !important;
|
|
}
|
|
|
|
// one primary vocabulary: the dark gold plate from _controls.scss
|
|
.wg-topbar .btn-primary,
|
|
.wg-topbar__register {
|
|
border: 1px solid var(--wg-gold-soft) !important;
|
|
color: #f0e6d8 !important;
|
|
background: linear-gradient(to bottom, #5a4a1a, #473914) !important;
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.06),
|
|
0 2px 8px rgba(0, 0, 0, 0.24);
|
|
}
|
|
|
|
.wg-topbar .btn-primary:hover,
|
|
.wg-topbar .btn-primary:focus,
|
|
.wg-topbar__register:hover,
|
|
.wg-topbar__register:focus {
|
|
border-color: var(--wg-gold) !important;
|
|
color: #fff4dd !important;
|
|
background: linear-gradient(to bottom, #6a5720, #53431a) !important;
|
|
}
|
|
|
|
.wg-topbar__login,
|
|
.wg-topbar__register {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 2.35rem;
|
|
border-radius: 6px;
|
|
padding: 0.35rem 0.78rem;
|
|
font-family: var(--wg-font-ui);
|
|
font-size: 0.86rem;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.wg-topbar__login {
|
|
color: var(--wg-text-soft);
|
|
border: 1px solid rgba(194, 163, 90, 0.2);
|
|
background: rgba(194, 163, 90, 0.055);
|
|
}
|
|
|
|
.wg-topbar__login:hover,
|
|
.wg-topbar__login:focus {
|
|
color: var(--wg-text);
|
|
border-color: rgba(194, 163, 90, 0.3);
|
|
background: rgba(194, 163, 90, 0.1);
|
|
}
|
|
|
|
.wg-topbar__burger {
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 2.4rem;
|
|
height: 2.4rem;
|
|
border: 1px solid rgba(194, 163, 90, 0.22);
|
|
border-radius: 6px;
|
|
color: var(--wg-text-soft);
|
|
background: rgba(194, 163, 90, 0.055);
|
|
}
|
|
|
|
.wg-topbar__burger:hover,
|
|
.wg-topbar__burger:focus {
|
|
color: var(--wg-text);
|
|
background: rgba(194, 163, 90, 0.1);
|
|
}
|
|
|
|
.wg-topbar__drawer {
|
|
display: none;
|
|
border-top: 1px solid rgba(194, 163, 90, 0.12);
|
|
background:
|
|
linear-gradient(180deg, rgba(255, 244, 221, 0.025), transparent 38%),
|
|
$wg-topbar-panel-bg;
|
|
}
|
|
|
|
.wg-topbar.is-drawer-open .wg-topbar__drawer {
|
|
display: block;
|
|
}
|
|
|
|
.wg-topbar__drawer-inner {
|
|
display: grid;
|
|
gap: 0.8rem;
|
|
width: min(100%, 42rem);
|
|
margin: 0 auto;
|
|
padding: 0.85rem;
|
|
}
|
|
|
|
.wg-topbar__drawer-search {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.55rem;
|
|
border: 1px solid rgba(194, 163, 90, 0.18);
|
|
border-radius: 8px;
|
|
padding: 0.5rem 0.65rem;
|
|
background: rgba(9, 8, 11, 0.45);
|
|
}
|
|
|
|
.wg-topbar__drawer-search input {
|
|
min-width: 0;
|
|
width: 100%;
|
|
border: 0;
|
|
color: var(--wg-text);
|
|
background: transparent;
|
|
outline: 0;
|
|
}
|
|
|
|
// The input's own outline is off; put the visible focus ring on its wrapper.
|
|
.wg-topbar__drawer-search:focus-within {
|
|
border-color: rgba(194, 163, 90, 0.5);
|
|
box-shadow: 0 0 0 1px var(--wg-focus);
|
|
}
|
|
|
|
.wg-topbar__drawer-nav,
|
|
.wg-topbar__drawer-actions,
|
|
.wg-topbar__drawer-auth {
|
|
display: grid;
|
|
gap: 0.35rem;
|
|
}
|
|
|
|
.wg-topbar__drawer-link,
|
|
.wg-topbar__drawer-actions a {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 0.55rem;
|
|
border: 1px solid rgba(194, 163, 90, 0.12);
|
|
border-radius: 7px;
|
|
padding: 0.62rem 0.7rem;
|
|
color: var(--wg-text-soft);
|
|
background: rgba(255, 244, 221, 0.02);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.wg-topbar__drawer-link:hover,
|
|
.wg-topbar__drawer-link:focus,
|
|
.wg-topbar__drawer-actions a:hover,
|
|
.wg-topbar__drawer-actions a:focus {
|
|
color: var(--wg-text);
|
|
border-color: rgba(194, 163, 90, 0.22);
|
|
background: var(--wg-border-soft);
|
|
}
|
|
|
|
@media (max-width: 1199.98px) {
|
|
.wg-topbar__inner {
|
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
}
|
|
|
|
.wg-topbar__nav {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 991.98px) {
|
|
.wg-topbar__inner {
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
}
|
|
|
|
.wg-topbar__utilities {
|
|
display: none;
|
|
}
|
|
|
|
.wg-topbar__burger {
|
|
display: inline-flex;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.wg-topbar__brand-mark {
|
|
width: 2rem;
|
|
height: 2rem;
|
|
}
|
|
|
|
.wg-topbar__brand-name {
|
|
font-size: 0.82rem;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
}
|