Skip to content

feat(cards): source & author/source stacks + aligned tags/date on feed cards#6331

Open
tsahimatsliah wants to merge 6 commits into
mainfrom
feat/collection-card-source-stack
Open

feat(cards): source & author/source stacks + aligned tags/date on feed cards#6331
tsahimatsliah wants to merge 6 commits into
mainfrom
feat/collection-card-source-stack

Conversation

@tsahimatsliah

@tsahimatsliah tsahimatsliah commented Jul 16, 2026

Copy link
Copy Markdown
Member

What

A cohesive redesign of collection / trend feed cards and the adjacent freeform / share (squad) cards so the feed grid reads as one system. ArticleGrid is intentionally untouched.

  1. Source stack replaces the pill. Collection/trend cards show the collection's own source avatars (CollectionSourceStack) instead of the static pill — resting tight (≤3 + a +N counter), expanding on hover with each source's rich hover card; expanded by default on mobile.
  2. Author + source stack on freeform & share cards. A shared AuthorSourceStack renders the author (primary, rounded-square) in front on the left and the source/squad (secondary, circle) behind on the right, overlapping and opening on hover — used by the freeform, poll, featured and share/squad headers. Single-avatar cards (e.g. articles) render unchanged.
  3. Tag + date alignment. Collection/trend and freeform cards adopt the ArticleGrid layout so tags + date bottom-anchor just above the footer, lining up in a mixed feed at any title length. Freeform posts now render tags; the redundant "N sources" is dropped from collection metadata.
  4. Hover-card data. The feed fetches the fields the source/author hover cards need. The source stats (description, membersCount, flags.totalUpvotes) are auth-gated on the API, so they're gated with @include(if: $loggedIn): logged-in users get the rich source card; logged-out users get a working feed and a graceful minimal card. (Fetching them unconditionally errors the logged-out feed.)

Where it shows in the product

FeedItemComponent dispatches these exact components for every feed (Collection → CollectionGrid/CollectionList, Freeform/Welcome → FreeformGrid/FreeformList, Share → ShareGrid, featured → the wide cards), and every feed query pulls FEED_POST_FRAGMENT — so all of the above render across the main feed, list/mobile layout and featured cards. Verified on the deployed webapp preview (logged-out feed renders; cards stack). CollectionPillSources / the collection post view are left on the pill.

Testing

  • CollectionGrid.spec.tsx updated; article/share/freeform/collection specs pass; lint + strict changed-file typecheck clean; full CI green.
  • Storybook story (Components/Cards/Collection Trend Card Tags) renders the real cards side by side for alignment review.
  • Feed verified on the webapp preview both logged-out (working feed, minimal source card) and via the API (logged-in fetches the rich stats).

Notes for reviewers

  • The source hover-card stats are login-gated by design because the API rejects them for anonymous users (this was the cause of an earlier logged-out feed break during development, now fixed).
  • zIndex in the stacks is set inline because this build doesn't emit Tailwind z-* utilities.

🤖 Generated with Claude Code

Preview domain

https://feat-collection-card-source-stac.preview.app.daily.dev

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
daily-webapp Ready Ready Preview Jul 18, 2026 10:23pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
storybook Ignored Ignored Jul 18, 2026 10:23pm

Request Review

tsahimatsliah added a commit that referenced this pull request Jul 16, 2026
Throwaway preview branch off the #6331 branch so the final aligned
collection / trend / freeform cards can be reviewed in Storybook:
- CollectionTrendCardTags: 4-column alignment matrix (freeform collection,
  image collection, default article, freeform post) at 1/2/3-line titles.
- CollectionSourceStack: source-stack states + hover playground.

Not intended for merge into the clean PR (#6331).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tsahimatsliah tsahimatsliah changed the title feat(cards): replace collection pill with source stack feat(cards): collection source stack + aligned card tags/date + freeform tags Jul 16, 2026
@tsahimatsliah
tsahimatsliah force-pushed the feat/collection-card-source-stack branch from 551997b to 53aa31a Compare July 16, 2026 15:10
@tsahimatsliah
tsahimatsliah force-pushed the feat/collection-card-source-stack branch from 53aa31a to 74cfe0f Compare July 16, 2026 20:48
@tsahimatsliah
tsahimatsliah requested a review from idoshamun July 16, 2026 21:28
@tsahimatsliah
tsahimatsliah force-pushed the feat/collection-card-source-stack branch from 165c208 to acdf693 Compare July 16, 2026 21:46
// tags/date bottom-anchor to the same row as the image cards and the
// default article card. pt-2 adds a bit of breathing room between the
// date and the text without growing the footer (box-border keeps min-h).
contentClassName="min-h-[10.5rem] pt-2"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the min-h-[10.5rem] concerns me, are we sure there's no impact here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — it's intentional and precisely derived, not arbitrary, and scoped only to here + FreeformGrid (no other caller passes contentClassName). The value makes the text footer's total height equal the cover-image footer, so the tag/date row bottom-anchors to the same row across both variants:

  • text footer: mt-1 (4px) + min-h-[10.5rem] (168px) = 172px
  • image footer: mt-2 (8px) + h-40 (160px) + mb-1 (4px) = 172px

min-height only sets a floor and the text is line-clamp-6, so there's no overflow/squash — a short post just reserves the same footer space an image card already does, keeping the grid rows aligned. Happy to switch to natural heights if you'd rather text cards not reserve it.

Comment on lines +661 to +668
name
image
username
permalink
bio
createdAt
reputation
isPlus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Double check that we actually need all the additional fields here, I'm not sure

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Trimmed in 2bb02a6. Kept only what UserEntityCard needs: id, username, permalink, createdAt are required by its render guard, plus name/image for the identity row. Dropped bio, reputation, isPlus — the card renders those conditionally and degrades gracefully without them, matching how the post.source hover fetches identity fields only.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Update — restoring bio, reputation, isPlus too. UserEntityCard renders all three (bio description, reputation badge, Plus badge); without them the author hover card is just avatar + name + joined date. Needed for the rich profile card by design.

Comment on lines +680 to +690
id
handle
name
image
permalink
type
description
membersCount
flags {
totalUpvotes
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Double check that we actually need all the additional fields here, I'm not sure

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Trimmed to match the post.source selection exactly — id, handle, name, image, permalink, type. Dropped description, membersCount, flags.totalUpvotes: SourceEntityCard reads those defensively (?? 0, description &&), so the hover degrades to identity-only, same as the existing article-card source hover. If we ever want real stats on source hovers we'd fetch them consistently for all of them (likely lazily).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Update — restoring these (description, membersCount, flags.totalUpvotes). They populate the source hover card's description + followers + upvotes counts, which is the intended design; without them the card renders empty ("0 Followers · 0 Upvotes", no description). They only ship for collection posts (collectionSources is null otherwise), and POST_BY_ID stays on handle+image (the post view renders the pill, not the hover card).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Final state: these fields are back but the stats (description, membersCount, flags.totalUpvotes) are now gated with @include(if: $loggedIn). Turns out they're auth-gated on the API — fetching them for logged-out users returns "Unexpected error" and nulls the whole feed query (verified against a real collection post). So: logged-in → rich source hover card; logged-out → working feed + a graceful minimal card. id/handle/name/image/permalink/type stay ungated (needed for the avatar + which-entity-card).

Comment thread packages/shared/src/graphql/posts.ts Outdated
Comment on lines +411 to +421
id
handle
name
image
permalink
type
description
membersCount
flags {
totalUpvotes
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Double check that we actually need all the additional fields here, I'm not sure

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Reverted — POST_BY_ID's collectionSources is back to handle, image (now unchanged from main). The collection post view, digest and brief render the pill (CollectionPillSourcesSourceAvatar), which only needs those two; the rich hover card is card-only.

Comment thread packages/shared/src/graphql/posts.ts Outdated
Comment on lines +507 to +517
id
handle
name
image
permalink
type
description
membersCount
flags {
totalUpvotes
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Double check that we actually need all the additional fields here, I'm not sure

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Reverted here too (static-fields query) — back to handle, image, same reasoning: the post view renders the pill, which only needs handle + image.

tsahimatsliah and others added 5 commits July 19, 2026 00:54
Replace the static Collection/Trend pill on collection feed cards with the
collection's own source avatars. New shared CollectionSourceStack:
viewport-aware, rests tight (<=3 avatars + a "+N" counter) and expands on
hover with each source's rich hover card; expanded by default on mobile.
Wired into CollectionCardHeader (grid + featured-wide) and CollectionList.
Spec updated: pill-label assertions -> source-stack render.
CollectionPillSources stays for the collection post view, digest and brief.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Shared AuthorSourceStack renders a post's author (primary, rounded-square)
in front on the left and the source/squad (secondary, circle) behind on
the right, overlapping and opening on hover — matching the collection
source stack. Each avatar keeps its own hover card. A single avatar (e.g.
an article with a source and no author) renders bare, so those cards are
unchanged. Used by SquadPostCardHeader (freeform/poll/featured) and
common/PostCardHeader (share/squad).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adopt the ArticleGrid layout so collection/trend and freeform post cards
bottom-anchor their tag chips + date just above the footer, lining up in a
mixed feed at any title length. Freeform post cards now render tags too.
Give the text preview the same footer height as the cover image
(WelcomePostCardFooter contentClassName + min-h) with a small gap above the
text. Drop the now-redundant "N sources" from the collection metadata (the
source stack shows it). ArticleGrid is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expand the feed author selection (name, image, permalink, bio, createdAt,
reputation, isPlus) and collectionSources selection so the source/author
hover cards render fully. The source stats (description, membersCount,
flags.totalUpvotes) are auth-gated on the API, so gate them with
@include(if: $loggedIn): logged-in users get the rich source card, logged-
out users get a working feed and a graceful minimal card. POST_BY_ID is
untouched (the post view renders the pill, which only needs handle+image).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Renders the real ArticleGrid / CollectionGrid / FreeformGrid side by side
at 1-, 2- and 3-line titles to review the tag/date alignment and the
source/author stacks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tsahimatsliah
tsahimatsliah force-pushed the feat/collection-card-source-stack branch from fa6d6d9 to b022e45 Compare July 18, 2026 21:54
@tsahimatsliah tsahimatsliah changed the title feat(cards): collection source stack + aligned card tags/date + freeform tags feat(cards): source & author/source stacks + aligned tags/date on feed cards Jul 18, 2026
@tsahimatsliah
tsahimatsliah force-pushed the feat/collection-card-source-stack branch from 526ecde to f76bd4e Compare July 18, 2026 22:13
The list-layout header (used on mobile and list mode) rendered the source
and author side-by-side. Render them through AuthorSourceStack when the
post has an author (and it isn't a collection), so freeform/share/squad
list cards show the same author-front / source-behind stack as the grid —
expanded on mobile, matching the collection list. Collection cards keep
their own source-stack children; article cards keep their single source.

AuthorSourceStack derives its resting overlap from the avatar size (like
CollectionSourceStack) instead of a hardcoded 32px.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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