fix(notifications): lead post rows with the headline, and let the time follow the grey text - #6548
Open
tsahimatsliah wants to merge 2 commits into
Open
fix(notifications): lead post rows with the headline, and let the time follow the grey text#6548tsahimatsliah wants to merge 2 commits into
tsahimatsliah wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
…e follow the grey text
User feedback on the redesigned notifications page: article headlines are hard
to focus on, and the old layout let you decide from the headline alone.
An inbox carries two genres of row. On a SOCIAL row ("Nimrod commented on your
post") the person is the payload, and the actor-first layout is right. On a
CONTENT-ARRIVAL row ("New post in The New Stack") the article headline is the
payload and the sentence is boilerplate that repeats on every row - yet the
boilerplate carried primary weight and colour while the headline sat at
typo-subhead / text-tertiary, the quietest text in the row. Four consecutive
rows from one source opened with the identical bold phrase.
Content-arrival rows now lead with the post title in primary weight, and the
announcing sentence becomes a quiet attribution built from the avatars rather
than the server copy: "The New Stack", or "Luffy in AI" for a squad post. The
words "New post in" are dropped - you are already in the notifications inbox and
the row has a cover, so they carry no information. Social rows keep the
actor-first layout untouched.
The timestamp moves off the title and follows the row's last grey line -
"The New Stack - 3h", "Scaling our cache layer - 5h" - so it reads as part of
the metadata trail rather than competing with the headline. A row with no grey
text at all (a bare follow) gets it on a line of its own.
Two things worth knowing for review:
- Every time-anchored grey line is a single-line truncating flex row with the
time as a shrink-0 sibling, never inside the clamp. Inline-inside-the-clamp is
how the old layout could hide the timestamp completely on a long title at
mobile width. The cost is that a comment snippet which is the last grey line
truncates to one line instead of two.
- The truncating text needs an explicit `shrink`: this codebase sets a global
`* { flex-shrink: 0 }`, and without it the text keeps its max-content width
and overflows the row. `multi-truncate` cannot be used in these rows at all -
it is `display: -webkit-box`, which blockifies when it becomes a flex item and
loses both its clamp and its width.
Adds tests for the promoted headline, the squad attribution, the actor-first
fallback when there is no post to promote, the timestamp anchoring, and that the
time is never inside a clamped element.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tsahimatsliah
force-pushed
the
feat/notification-row-readability
branch
from
August 27, 2026 14:03
a3a23fc to
04503a0
Compare
…dit framing The notification stories render the real component, so they pick up the new layout on their own - but their prose described the old one and would have shipped stale with it. - List item / Row anatomy (new): the two genres, the attribution rule and the timestamp rule, each with a live row. Also the two CSS traps, because both cost a debugging round during implementation and neither is visible from the code. - Overview: was framed as an open "readability audit" with levers to tune. The audit is finished, so it now opens with the rules it produced. Its levers for the list row described a bold title and a meta line carrying the time - neither is true any more. - Full page / Use cases: point at the anatomy story rather than describing the layout twice. - In-app popup: records a KNOWN GAP. InAppNotificationItem renders the title and nothing else, so a post arrival still reads "New post in <source>" there while the feed row leads with the headline. The avatar lockup is shared, the text layout is not. Documented rather than silently changed - it is a different surface and deserves its own decision. Untouched stories with pre-existing prettier drift (Icons, Toast, _mock) are deliberately left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The feedback
The complaint is precise and the code confirms it.
Diagnosis
An inbox carries two genres of row:
The redesign applied the social template to both. On a content-arrival row that inverts the hierarchy:
"New post in <b>The New Stack</b>"getstypo-callout/text-text-primary, while the headline — the only thing that decides a click — drops totypo-subhead/text-text-tertiary. On a subscribed feed most rows are content arrivals, so four consecutive rows open with the identical bold phrase and the eye has to skip past the repeated part to reach the varying part.This is 100% rolled out (
pages/notifications.tsxrendersNotificationsFeedunconditionally;NotificationItemLegacyis orphaned), so there is no flag to roll back — it needs a targeted change to the row.The change
Content-arrival rows (
SourcePostAdded/SquadPostAdded/UserPostAdded) lead with the post title in primary weight. The announcing sentence becomes a quiet attribution built from the avatars rather than the server copy —The New Stack, orLuffy in AIfor a squad post. The words "New post in" are dropped: you are already in the notifications inbox and the row carries a cover, so they carry no information.Social rows are untouched. Same actor-first layout, same wording.
The timestamp moves off the title and follows the row's last grey line —
The New Stack · 3h,Scaling our cache layer · 5h— so it reads as part of the metadata trail instead of competing with the headline. A row with no grey text at all (a bare follow) gets it on a line of its own.Before / after on a source-post row:
Two things worth a reviewer's attention
The time is never inside a line-clamp. Every time-anchored grey line is a single-line truncating flex row with the time as a
shrink-0sibling. This is not stylistic: inline-inside-the-clamp is how the current layout can hide the timestamp entirely — a headline long enough to fill two lines clamps it away, which is reproducible at mobile width today. There is a test pinning this.The cost: a comment snippet that is the row's last grey line truncates to one line instead of two. Rows where the comment is followed by a post title keep both lines. Called out because it is a real trade, not an oversight.
Two CSS traps in this codebase, both found by rendering rather than reading:
* { flex-shrink: 0 }means truncating text must opt back in withshrink, or it keeps its max-content width and overflows the row instead of ellipsing.multi-truncateisdisplay: -webkit-box, which blockifies when it becomes a flex item — losing both the clamp and the width. It cannot be used for the anchored lines at all, which is why those take a different branch.Verification
packages/sharednotifications suites: 48 passed (4 suites)packages/webappNotificationsPage: 4 passedsrc/components/notifications: clean,--max-warnings 0tsc --noEmit: 26 errors, all pre-existing onmain, none in changed filesComponents/Notifications/Full page) in light + dark, desktop + 375px + 300px; no horizontal overflow (body.scrollWidth === clientWidth), and all timestamps survive at 300pxNew tests cover the promoted headline, squad attribution, the actor-first fallback when there is no post to promote, timestamp anchoring, and the no-grey-text case.
Provenance
Design was chosen by simulating the alternatives in Storybook rather than by argument — six headline treatments and seven timestamp treatments, on a shared feed, with row heights and timestamp positions measured in the DOM. Two candidates were killed by measurement (one lost the timestamp at mobile width; one bought no density at all because the 48px cover sets the row height, not the text). Those exploration pages are on
feat/notification-headline-emphasisand deliberately kept out of this PR.🤖 Generated with Claude Code
Preview domain
https://feat-notification-row-readabilit.preview.app.daily.dev