Two polish improvements to the aggregated notifications inbox:
- Per-node filter dropdown in the bell panel (hidden on single-node
installs) so fleet operators can triage events from a specific box.
Selected node falls back to "All nodes" automatically if that node is
removed from the registry.
- 60-second safety-net poll that reconciles the list so events missed
during a WebSocket reconnect backoff appear without a manual refresh.
Uses a ref indirection to pin the interval to the latest
fetchNotifications closure.
Extract the app header into a dedicated TopBar component and apply the
same translucent chrome language used by the sidebar: bg-sidebar +
backdrop-blur-md + inset top highlight. A new --chrome-top-highlight
token drives the highlight in both themes via the shadow-chrome-top
utility alias.
Restore the pulsing-dot unread indicator on the notification bell
(replaces the temporary count pill) and keep its aria-label dynamic so
screen readers still hear the unread count. Tighten nav a11y with
aria-current on the active item, aria-label on icon-only buttons, and a
proper <nav> landmark around the desktop Highlight group.
Swap hardcoded Tailwind padding on NodeSwitcher, UserProfileDropdown,
and NotificationPanel for var(--density-row-x) / --density-row-y /
--density-cell-y / --density-tile-y custom properties so the three
sidebar/header overlays now tighten when the Appearance setting is
switched to Compact, matching the reference pattern in ui/table.tsx.
Add stack_name and container_name columns to notification_history so bell
rows can act as jump points. Producers (AutoHeal, Docker events) pass the
container context through dispatchAlert; the panel renders routable rows
as buttons that load the target stack and, when a container name is
present, open its logs modal. Non-structural notifications stay as
passive display rows.
* feat(ui): redesign user menu and notification panel per design audit
Align both floating surfaces with the stack-view design language: cyan
signal rails, identity headers, strip containers, day-banded streams,
severity rails, Instrument Serif for hero words, and tracked-mono for
metadata. Extract the notifications popover out of EditorLayout into its
own component and introduce a reusable SegmentedControl primitive for
3-way radiogroups (Auto/Light/Dark theme, All/Unread/Alerts filter).
* fix(ui): pin accessible names on avatar and bell buttons
After the redesign the avatar button's text content became the user's
initials and the bell button's text became the unread count, which
displaced the title-based accessible names and broke
getByRole('button', { name: /profile/i }). Set aria-label explicitly on
both triggers and mark the bell badge aria-hidden so screen readers and
role-based selectors see stable names regardless of dynamic content.