Skip to content

Show article read status on grid cards and unify card overlays - #704

Merged
fredrivett merged 4 commits into
mainfrom
fredrivett/card-overlays
Nov 14, 2026
Merged

fredrivett merged 4 commits into
mainfrom
fredrivett/card-overlays

Conversation

@fredrivett

@fredrivett fredrivett commented Nov 14, 2026 •

Copy link
Copy Markdown
Owner

What & why

Grid cards didn't show whether an article had been read, and the overlays cards draw differed by kind: YouTube/Vimeo badges were brand-coloured while X/Instagram were translucent black, the book status badge was larger, product price and document page-count tags were fixed px (not scaling with grid density) with a different radius and opacity from the GIF/duration tags, and the tweet play button was fixed px while the video one scaled.

  • Shared overlay primitives (components/ui/card-overlay.tsx): CardCornerBadge (top right, optional hover label), CardTag (bottom corners) and CardPlayIndicator, with one surface (bg-black/60 + blur), one inset and em sizing. Tweets, Instagram, video, book status, product price and document page count all use them. Text-only tweets pad the author row so a long name truncates before the X badge.
  • Article read status: owners see a dot (unread) / check (read) corner badge on article cards, with "Unread" / "Read" on hover, matching the book status badge. It's owner-only, like the detail view's read toggle. Webpages have no read status, so no badge.
  • Layout: coverless article titles reserve room for the badge (ARTICLE_TITLE_BADGE_INSET_EM). The frame estimate can't tell who's viewing, so every article reserves it, and card-frame.ts mirrors it so reserved heights stay right.

Checklist

  • User-facing change → added/updated a PostHog event (and a funnel/insight for a new flow), or N/A: N/A, display only; no new action (marking read is the existing detail-view toggle)
  • User-facing or service change → docs updated (README features/roadmap/services, .env.example, in-app help, CONTRIBUTING.md, onboarding checklist), or N/A: N/A, no help page covers grid card badges or article read status today
  • New error paths report via captureServerException / the error boundary, or N/A: N/A, no new error paths
  • New behavior is covered by tests, or N/A: ArticleReadStatusBadge RTL test (read/unread branch + accessible label); Grid/CardFit stories gain a long-title article (title inset) and a webpage (no inset) case so the estimate can't drift; new Grid/CardOverlays story renders every overlay
  • User-facing change → demo video attached (record-pr-demo skill); refactor through a user flow → parity run, or N/A: before/after below
  • If this fixes a recurring defect, considered a guardrail via the learn skill, or N/A: N/A, not a defect fix

Demo

Same seeded grid on both takes (3 articles, the third already read; a text tweet; a YouTube video; a book), pointer visiting each corner badge.

❌ Before

pr-card-overlays-before.mp4

✅ After

pr-card-overlays-after.mp4

Notes

  • Verified: bun run check:fix, full unit suite (bun run test), and the storybook tests for Grid/CardFit, Grid/CardOverlays, item card states, tweet/article/book stories. Checked light, dark and a 0.75 grid font scale in the overlay story, plus the hover label (headless Chrome needs a hover-capable pointer emulated for hover: styles).
  • Not shown in the demo: toggling read in the detail view. On the demo stack (no Trigger.dev key) the item PATCH writes read_at then 500s on the room-sync trigger, which is an existing issue unrelated to this PR.
  • Design calls worth a look: video badges are no longer brand-coloured; the book badge is slightly smaller (matches the platform badges); the hover label overlaps the end of a title's first line while open, as the book badge already did.
  • Commits: shared overlay primitives first (no new feature), then the article read badge.

Platform badges, book status badge, bottom tags (GIF, duration, price,
page count) and play indicators now share one surface, inset and em
sizing via CardCornerBadge / CardTag / CardPlayIndicator, so they scale
with grid density and match across kinds. Price and page count were
fixed px; video badges were brand-coloured; the book badge was larger.
Text-only tweets pad the author row so a long name truncates before the
X badge.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1dc41-2136-774d-8d32-d3af4eded62a
Owners see an Unread (dot) / Read (check) corner badge on article cards,
with the label on hover, matching the book status badge. Coverless
article titles reserve room for the badge, mirrored in the frame
estimate so the reserved height stays correct for every viewer. Adds a
Grid/CardOverlays story showing every overlay, and CardFit cases for a
long-title article and webpage.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1dc41-2136-774d-8d32-d3af4eded62a
@vercel

vercel Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
abode Ignored Ignored Preview Nov 14, 2026 11:40pm UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 14 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread app/src/components/ui/card-overlay.tsx Resolved
Rooms keep their items in local state, so a read toggle or book status
change saved from the dialog left the room card's badge stale. Items the
API returns through useReplaceCachedItem now also reach subscribed local
lists (useOnReplacedCachedItem); the room merges them, keeping its own
roomItemId and room addedAt. Also: reduced-motion guard on the play
indicator's hover scale, a real TwitterCard GIF in the overlay story,
and a precise titleInset doc.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1dc41-2136-774d-8d32-d3af4eded62a

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread app/src/lib/api-hooks.ts Resolved
The room listener now fires from replaceCachedItem, so retry/reassign
refreshes (useRefreshCachedItems) reach the room too, and the room skips
a copy older than its own (isNewer), as the caches do, so an out-of-order
save can't revert a badge.
@fredrivett
fredrivett merged commit 693eb4d into main Nov 14, 2026
14 checks passed
@fredrivett
fredrivett deleted the fredrivett/card-overlays branch November 14, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants