Inbox: replace 4 parallel outlined buttons with 2 context-aware ones.
When nothing is selected → "Acknowledge all firing" (primary) + "Mark all
read" (secondary). When rows are selected → the same slots become
"Acknowledge N" + "Mark N read" with counts inlined. Primary variant
gives the foreground action proper visual weight; secondary is the
supporting action. No more visually-identical disabled buttons cluttering
the bar.
History: drop the local DateRangePicker. The page now reads
`timeRange` from `useGlobalFilters()` so the top-bar TimeRangeDropdown
(1h / 3h / 6h / Today / 24h / 7d / custom) is the single source of
truth, consistent with every other time-scoped page in the app.
Surfaced during second smoke:
1. Notification bell moved — was first child of TopBar (left of
breadcrumb); now rendered inside the `environment` slot so it
sits between the env selector and the user menu, matching user
expectations.
2. Content tabs (Exchanges/Dashboard/Runtime/Deployments) hidden on
`/alerts/*` — the operational tabs don't apply there.
3. Inbox / All alerts filters now actually filter. `AlertController.list`
accepts only `limit` — `state`/`severity` query params are dropped
server-side. Move `useAlerts` to fetch once per env (limit 200) and
apply filters client-side via react-query `select`, with a stable
queryKey so filter toggles are instant and don't re-request. True
server-side filter needs a backend change (follow-up).
4. Novice-friendly labels:
- Inbox subtitle: "99 firing · 100 total" → "99 need attention ·
100 total in inbox"
- All alerts filter: Open/Firing/Acked/All →
"Currently open"/"Firing now"/"Acknowledged"/"All states"
- All alerts subtitle: "N shown" → "N matching your filter"
- History subtitle: "N resolved" → "N resolved alert(s) in range"
- Rules subtitle: "N total" → "N rule(s) configured"
- Silences subtitle: "N active" → "N active silence(s)" or
"Nothing silenced right now"
- Column headers: "State" → "Status", rules "Kind" → "Type",
rules "Targets" → "Notifies"
- Buttons: "Ack" → "Acknowledge", silence "End" → "End early"
Updated alerts.test.tsx and e2e selector to match new behavior/labels.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Visual regressions surfaced during browser smoke:
1. Page headers — `SectionHeader` renders as 12px uppercase gray (a
section divider, not a page title). Replace with proper h2 title
+ inline subtitle (`N firing · N total` etc.) and right-aligned
actions, styled from `alerts-page.module.css`.
2. Undefined `--space-*` tokens — the project (and `@cameleer/design-system`)
has never shipped `--space-sm|md|lg|xl`, even though many modules
(SensitiveKeysPage, alerts CSS, …) reference them. The fallback
to `initial` silently collapsed gaps/paddings to 0. Define the
scale in `ui/src/index.css` so every consumer picks it up.
3. List scrolling — DataTable was using default pagination, but with
no flex sizing the whole page scrolled. Add `fillHeight` and raise
`pageSize`/list `limit` to 200 so the table gets sticky header +
internal scroll + pinned pagination footer (Gmail-style). True
cursor-based infinite scroll needs a backend change (filed as
follow-up — `/alerts` only accepts `limit` today).
4. Title column clipping — `.titlePreview` used `white-space: nowrap`
+ fixed `max-width`, truncating message mid-UUID. Switch to a
2-line `-webkit-line-clamp` so full context is visible.
5. Notification bell badge invisible — `NotificationBell.module.css`
referenced undefined tokens (`--fg`, `--hover-bg`, `--bg`,
`--muted`). Map to real DS tokens (`--text-primary`, `--bg-hover`,
`#fff`, `--text-muted`). The admin user currently sees no badge
because the backend `/alerts/unread-count` returns 0 (read
receipts) — that's data, not UI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces custom feed rows with DataTable. Adds a DateRangePicker
filter (client-side) defaulting to the last 7 days. Client-side
range filter is a stopgap; a server-side range param is a future
enhancement captured in the design spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 6 lazy-loaded route entries for the alerting UI (Inbox, All, History,
Rules list, Rule editor wizard, Silences) plus an `/alerts` → `/alerts/inbox`
redirect. Page components are placeholder stubs to be replaced in Phase 5/6/7.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>