From 317738ed7998a7af5abe0b64769941cb11808ab2 Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Thu, 28 May 2026 11:31:34 -0700 Subject: [PATCH] =?UTF-8?q?v0.21.0=20header+inbox=20UX=20(#24,#25,#31):=20?= =?UTF-8?q?rename=20About=E2=86=92Philosophy,=20inline-SVG=20inbox=20icon,?= =?UTF-8?q?=20light=20inbox=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #24: header link "About" → "Philosophy" (route/title unchanged). - #25 icon: replace 📮 emoji with a dependency-free inline-SVG envelope in .inbox-trigger; aria-label/title reframed to "Inbox". Badge intact. - #25 inbox UX (light, no redesign): sharper unread/read distinction (accent dot + left bar + tint via tokens), per-row "mark as read" affordance that marks-without-navigating, clearer "Mark all read" label, and a real empty/caught-up state. New Inbox.css is tokenized and written one notch more specific than App.css where it overrides (Inbox.css injects before App.css under ESM eval order). Data flow, API calls, routing-on-click, and badge behavior preserved. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/App.jsx | 14 +++- frontend/src/components/Inbox.css | 128 ++++++++++++++++++++++++++++++ frontend/src/components/Inbox.jsx | 67 +++++++++++++--- 3 files changed, 195 insertions(+), 14 deletions(-) create mode 100644 frontend/src/components/Inbox.css diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 3a5dca1..e7dfb88 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -169,7 +169,7 @@ export default function App() { wonders why a conversation is public can reach the answer in two clicks. Anonymous viewers see it too. */} - About + Philosophy Docs @@ -188,9 +188,17 @@ export default function App() {
- {loading &&

Loading…

} + {loading &&

Loading your inbox…

} {!loading && items.length === 0 && ( -

No notifications match. Try a different filter, or come back later.

+
+

You're all caught up.

+

+ {filters.unread || filters.rfcSlug || filters.category + ? 'Nothing matches the current filters. Clear them to see everything.' + : 'New activity on RFCs you follow will show up here.'} +

+
)}
    {items.map(item => ( - + ))}
@@ -145,16 +164,24 @@ export default function Inbox({ onClose, lastChangeTick }) { ) } -function InboxRow({ item, onClick, onClose }) { +function InboxRow({ item, onClick, onMarkRead, onClose }) { const unread = !item.read_at const target = deepLink(item) const handle = async () => { await onClick(item) if (target) onClose?.() } + const handleMarkRead = async (e) => { + // Don't let the row's Link fire — this affordance only marks read, + // it never navigates. + e.preventDefault() + e.stopPropagation() + await onMarkRead(item) + } return ( -
  • +
  • + {item.category || '·'} {item.summary} {item.bundled_count > 1 && ( @@ -162,6 +189,24 @@ function InboxRow({ item, onClick, onClose }) { )} {formatWhen(item.created_at)} + {unread && ( + + )}
  • ) }