Skip to content

Home's action centre badges its CAPPED list while the bell badges every unread topic — 5 and 9 for the same question, on one page #4329

Description

@yinlianghui

Found while implementing #4225 / #4316 (PR #4327). Not fixed there: that PR's
scope is read-state and the duplicate read, and this is a counting question the
two cards never agreed on. Pre-existing, and unchanged by that PR.

What

Two panels on /home badge "what needs me", and they count different things:

surface badge window
bell — layout/InboxPopover.tsx distinct unread topics + pending approvals the feed's full 20 rows
Home action centre — console/home/HomeRail.tsx pendingApprovalsCount + notifications.length the list it renders, capped at limit (5)

HomeActionCenter computes const total = pendingApprovalsCount + notifications.length,
and notifications is what the card renders — which useHomeInbox caps at
limit, default 5. So the badge is "how many rows are on show", not "how much is
waiting".

With nine unread messages a user sees 9 on the bell and 5 two hundred
pixels below, for the same question about the same rows.

Measured

PR #4327 pins the current numbers, so the disagreement is in-tree and explicit —
packages/app-shell/src/hooks/__tests__/sharedInboxFeed.twoSurfaces.test.tsx,
case "an unread message with no receipt at all still counts": nine unread rows,
homeBadge() is '5' while inbox-bell-badge reads '9'. That case asserts
both numbers deliberately; it is describing today's behaviour, not endorsing it.

Observation-class, and why it is filed anyway

The card is self-consistent — it lists five things and badges five — and nothing
is stale or wrong on either surface. No user is blocked. So this is a finding,
not a defect, and it is left unlabelled for pm:queue deliberately.

What makes it worth recording is that the ceiling moved. Before #4225 Home's
read was $top: 5, so the card genuinely could not know there were nine — the
badge could not have said anything else. Both surfaces now derive from one feed
holding the bell's 20 already-joined rows, so the true unread count is in
hand at Home's call site; the cap is now a presentation slice over data the card
already has. Making the badge count the unread set while the list stays capped is
a two-line change today and was impossible last week.

It also sits directly against the theme both #4225 and #4316 were closed on —
two surfaces reading one feed should not present two numbers for one question —
so leaving it unrecorded invites someone to rediscover it as a bug report.

Options, if it is ever picked up

  1. Badge the unread count, keep the list capped (recommended shape): badge 9,
    list the newest 5. Matches the bell's own semantics, and matches how a capped
    list normally behaves elsewhere. Costs a new prop on HomeActionCenter, since
    the count would no longer be derivable from notifications.length.
  2. Leave it. Defensible: "5 things shown, badge 5" is honest about the card,
    and the bell is the surface that owns the total.

Not obviously worth doing on its own — most likely a rider on the next change to
this card.

Pointers

  • packages/app-shell/src/console/home/HomeRail.tsxHomeActionCenter, total
  • packages/app-shell/src/hooks/useHomeInbox.ts — the .slice(0, limit) cap
  • packages/app-shell/src/layout/InboxPopover.tsxunreadTopics, the bell's fold
  • packages/app-shell/src/hooks/sharedUserFeeds.ts — the shared 20-row window

Generated by Claude Code

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions