Topbar unread drawer (#28)
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)
Reviewed-on: #28
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit was merged in pull request #28.
This commit is contained in:
@@ -148,3 +148,35 @@ assertExcludes(
|
||||
'brand-header',
|
||||
'Removed brand banner widget area should not remain registered'
|
||||
);
|
||||
|
||||
const unreadDrawer = read('templates/partials/header/unread-drawer.tpl');
|
||||
assertIncludes(
|
||||
topbar,
|
||||
'<!-- IMPORT partials/header/unread-drawer.tpl -->',
|
||||
'Topbar should mount the unread drawer before notifications'
|
||||
);
|
||||
assert(
|
||||
topbar.indexOf('partials/header/unread-drawer.tpl') < topbar.indexOf('partials/sidebar/notifications.tpl'),
|
||||
'Unread drawer should sit before the notifications item'
|
||||
);
|
||||
assertIncludes(
|
||||
unreadDrawer,
|
||||
'component="unread/count"',
|
||||
'Unread toggle should carry the live core count badge'
|
||||
);
|
||||
assertIncludes(
|
||||
unreadDrawer,
|
||||
'data-wg-unread-menu',
|
||||
'Unread dropdown menu should expose the JS mount hook'
|
||||
);
|
||||
assertMatches(
|
||||
topbar,
|
||||
/href="\{relative_path\}\/unread"[^>]*>[\s\S]*?component="unread\/count"/,
|
||||
'Mobile drawer actions should include an Unread link with count badge'
|
||||
);
|
||||
|
||||
assertIncludes(
|
||||
stylesheet,
|
||||
'.unread-dropdown',
|
||||
'Topbar styles should cover the unread dropdown'
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user