Adds an Unread dropdown to the topbar utilities (before notifications), per docs/superpowers/plans/2026-07-17-topbar-unread-drawer.md.
New partial templates/partials/header/unread-drawer.tpl: toggle with live component="unread/count" badge (core socket updates), server-rendered empty/footer rows.
public/client.js: on dropdown open, fetches GET /api/unread and injects up to 10 topic rows (titles/categories via textContent only); fetch failure falls back to the empty state.
Mobile burger drawer gets an Unread row with the same badge.
SCSS: unread dropdown joins the shared dropdown width rule; flex row styles for topic items.
Deviations from the plan's example code, found by live verification against the dev forum:
Plan's api.get('/unread') hits the v3 write API and 404s → replaced with a fetch of the /api/unread read route.
NodeBB 4 has no global window.require, so runtime translation of the static [[unread:...]] strings never ran → those strings are now server-rendered in the template (also removes the plan's translate-over-innerHTML step, which would have re-parsed untrusted titles as HTML).
Verified: full plain-node test suite passes; Playwright against the dev container passed all checks (badge count, item ordering before notifications, dropdown topic links + navigation, /unread footer link, mobile drawer badge at 390px).
Adds an Unread dropdown to the topbar utilities (before notifications), per docs/superpowers/plans/2026-07-17-topbar-unread-drawer.md.
- New partial `templates/partials/header/unread-drawer.tpl`: toggle with live `component="unread/count"` badge (core socket updates), server-rendered empty/footer rows.
- `public/client.js`: on dropdown open, fetches `GET /api/unread` and injects up to 10 topic rows (titles/categories via textContent only); fetch failure falls back to the empty state.
- Mobile burger drawer gets an Unread row with the same badge.
- SCSS: unread dropdown joins the shared dropdown width rule; flex row styles for topic items.
Deviations from the plan's example code, found by live verification against the dev forum:
- Plan's `api.get('/unread')` hits the v3 write API and 404s → replaced with a fetch of the `/api/unread` read route.
- NodeBB 4 has no global `window.require`, so runtime translation of the static `[[unread:...]]` strings never ran → those strings are now server-rendered in the template (also removes the plan's translate-over-innerHTML step, which would have re-parsed untrusted titles as HTML).
Verified: full plain-node test suite passes; Playwright against the dev container passed all checks (badge count, item ordering before notifications, dropdown topic links + navigation, /unread footer link, mobile drawer badge at 390px).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Translating menuEl.innerHTML re-serialized untrusted topic titles into
HTML and reinjected them via innerHTML. Translate only the two static
placeholder strings ([[unread:no-unread-topics]], [[unread:title]])
via a small textContent-based helper instead.
window.require is undefined in the NodeBB 4 webpack client build, so the
translateText helper never ran and unread drawer strings rendered as raw
[[unread:title]] / [[unread:no-unread-topics]]. Move the static strings into
the benchpress template (translated at render time) and have client.js only
manage the topic <li> rows.
archvillainette
scheduled this pull request to auto merge when all checks succeed 2026-07-17 16:42:18 +00:00
xtul
approved these changes 2026-07-17 16:43:11 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Adds an Unread dropdown to the topbar utilities (before notifications), per docs/superpowers/plans/2026-07-17-topbar-unread-drawer.md.
templates/partials/header/unread-drawer.tpl: toggle with livecomponent="unread/count"badge (core socket updates), server-rendered empty/footer rows.public/client.js: on dropdown open, fetchesGET /api/unreadand injects up to 10 topic rows (titles/categories via textContent only); fetch failure falls back to the empty state.Deviations from the plan's example code, found by live verification against the dev forum:
api.get('/unread')hits the v3 write API and 404s → replaced with a fetch of the/api/unreadread route.window.require, so runtime translation of the static[[unread:...]]strings never ran → those strings are now server-rendered in the template (also removes the plan's translate-over-innerHTML step, which would have re-parsed untrusted titles as HTML).Verified: full plain-node test suite passes; Playwright against the dev container passed all checks (badge count, item ordering before notifications, dropdown topic links + navigation, /unread footer link, mobile drawer badge at 390px).
🤖 Generated with Claude Code