9e6756f678
Backfills transcripts that existed only locally in ohm-infra: - 0019.1/.2/.3 - UX-polish wave subagent transcripts (driver 0019.0 never finalized) - 0026.1-.9 - security-audit-0026 subagent transcripts (driver abandoned/closed-out by 0068; audit drove published 0030 remediation) - 0073.0 - PPE/progressive-delivery + engineering-handbook session, originally drafted as a duplicate 0046.0; reassigned next free number (0072 taken by a concurrent session) sessions.json: add 0019/0073 titles, update 0026 title. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.9 KiB
4.9 KiB
SESSION-0019.2 — header rename + inbox icon + light inbox UX
Parent: SESSION-0019.0-TRANSCRIPT-… (UX-polish wave, rfc-app v0.21.0) Subsession: 0019.2 Window: 2026-05-28T11-27 → 2026-05-28T11-31 (PST)
Goal
Roadmap #24 (rename), #25 (inbox icon + light inbox UX), and the header's share of #31 polish — confined to the App.jsx header region, Inbox.jsx, and a new Inbox.css. No version/changelog/tag/merge/push.
Pre-state
- Branch
feature/v0.21.0-header-inboxat the foundation commit (token modulefrontend/src/styles/tokens.csspresent). - Header link text was "About" (already routing to /philosophy).
- Inbox trigger used a 📮 emoji with title "Notifications inbox (§15.2)".
- Inbox.jsx: working panel; row click marks-read + navigates; one
"Mark all read (under filter)" button; terse empty copy; no per-row
mark-read; unread indicated only by
.inbox-row.unreadbg tint. - No Amplitude
track()calls inside Inbox.jsx (only api.js calls: listNotifications, markNotificationRead, markNotificationsReadByFilter). So "preserve §15 tracking" = don't break the data path; nothing to add.
Turn-by-turn arc (honest)
- Read tokens.css, the App.jsx header block (~150–238), Inbox.jsx full, and the §15 inbox block of App.css (1573–1641) to learn existing class names + property values before touching anything.
- #24: one-word change "About" → "Philosophy" (kept the title attr).
- #25 icon: replaced
<span>📮</span>with a hand-rolled inline SVG envelope (18×18, viewBox 0 0 24 24, stroke=currentColor, ~1.75 stroke, rounded). Setaria-label="Inbox", retitled "Inbox (§15.2)". Badge block untouched. - #25 UX: refactored Inbox.jsx. Extracted
markOneRead(item)(used by both row-click and the new per-row affordance) which also decrements the local unreadCount. Added aninbox-unread-dotspan +read/unreadrow class, a per-row "Mark as read" button (inline check SVG) that sits OUTSIDE the Link andpreventDefault/stopPropagations so it marks without navigating, shown only for unread rows. Simplified the mark-all label to "Mark all read" with an explanatory title. Replaced empty copy with a "You're all caught up." state that branches on whether filters are active. - Wrote Inbox.css (tokenized). Discovered via import order that Inbox.jsx
is imported at App.jsx line 6, BEFORE App.css at line 30 — so under
ESM depth-first eval Inbox.css injects FIRST and App.css wins ties.
Wrote override rules one notch more specific (
.inbox-list .inbox-row…) and.inbox-empty .mutedto beat global.muted. New classes need no guard. All values via var(--space/-text/-color/-radius/-motion/-ease). - Build: first
npm run buildfailed — VITE_APP_NAME required (config guard, unrelated to my change; no .env in worktree). Re-ran withVITE_APP_NAME="OHM RFC" npm run build→ green (expected ~971kB chunk warning only). - Verified
git statusshows only App.jsx + Inbox.jsx modified and Inbox.css new (node_modules symlink left untracked). Committed exactly those three.
Cut state
- Branch:
feature/v0.21.0-header-inbox - Final commit: 317738ed7998a7af5abe0b64769941cb11808ab2
- Files changed: frontend/src/App.jsx (header region only), frontend/src/components/Inbox.jsx, frontend/src/components/Inbox.css (new)
- Build: green (chunk-size warning only).
What the driver needs to know (inbox UX review pointers)
The inbox pass is LIGHT — same layout, panel, filters, bundle toggle, deep-links, and API calls as before. Exactly what changed for review:
- Unread/read: unread rows now get an accent left-bar (inset box-shadow)
- warm tint + a filled accent dot + medium-weight summary; read rows drop the dot (space reserved, stays aligned) and mute the summary.
- Per-row affordance: a check-icon button appears on row hover/focus
(always visible on touch via
@media (hover:none)) that marks the row read without navigating. Uses the same markOneRead path. - Mark-all: relabeled "Mark all read" (+ title clarifying it's
filter-scoped). Same
markNotificationsReadByFiltercall, same disabled-when-all-read guard. - Empty state: "You're all caught up." with filter-aware sub-copy.
- Behavior preserved: row-click still marks-read then navigates + closes; unreadCount now also decremented locally on single marks (was only reset to 0 on mark-all before — minor, improves badge accuracy, SSE still authoritative per §15.3).
§19.2 candidates
- Full inbox redesign deferred to a #25-followup: the operator's reference screenshot did not transmit, so this stayed a polish pass within the existing structure rather than a re-layout. Revisit with the screenshot.
- The inbox-trigger / inbox-* base rules still live in App.css with hardcoded hex (a sibling is tokenizing App.css this wave). If that sweep lands, the few overrides in Inbox.css could shed their extra-specificity guards once import order is normalized.