Add feed hero section with carousel, highlights, and ad placement - #6515
Open
tsahimatsliah wants to merge 18 commits into
Open
Add feed hero section with carousel, highlights, and ad placement#6515tsahimatsliah wants to merge 18 commits into
tsahimatsliah wants to merge 18 commits into
Conversation
Adds a hero section for the top of the feed, plus a Storybook page to iterate on it: - FeedHeroCarousel: pages through featured posts with the existing featured-wide cards, dot indicators and prev/next chips labelled with the neighbouring headlines. - FeedHeroAd: a compact native/direct ad placement for the rail, built from the existing ad primitives (link, image, attribution, pixel, viewability). - FeedHeroSection: carousel on the left, rail on the right with the ad slot, the Happening Now highlights card and an Explore all CTA. - FeedSectionToolbar: section title with search, filter and bookmark actions for the row above the tag chips. Nothing renders this yet — the layout lives in Storybook under Features/Feed/Hero, composed with the existing ExploreChipsBar and feed cards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
The rail placement led with a call-to-action button that dominated a 20rem card, even though the whole card is already a click target. It now carries the same elements as the feed ad card and nothing else: advertiser logo and disclosure, the ad title, matching tags, and the cover image in its own column. Also adds the Storybook coverage needed to review it: responsive breakpoints rendered in per-width iframes, hero section states (no ad, single post, short highlights list), one carousel case per post type, ad placement variants, and toolbar variants. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
…obile Follow-up on the hero section review: - Drops the "Explore all" button; the highlights card already ends in "Read all". - Flattens the rail: the ad slot and the highlights card lose their background and border, keeping only a hover tint on the ad. - Replaces the two headline-labelled paging buttons with a position counter and two arrow buttons, right-aligned. The headline moves to a tooltip and stays in the button's aria-label. - Renders the featured post through the feed's own list card below laptop, so the top of the mobile feed matches the rest of it. The post-type-to-list-card map moves out of FeedItemComponent into cards/common/listCards.ts so both callers share one map. - Renames the section heading to "Recommended for you" in the story. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
The dots on the left already show which post is showing, so the counter next to the arrows was a second readout of the same thing. Shortens the section heading to "Recommended" in the story too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
Puts the hero section on the real feed so it can be reviewed with live data. Off by default behind the `feed_hero` flag. - FeedHero fetches the six current `majorHeadlines` for the Happening Now list, then loads the top four of those headlines' posts in full through `feedByIds` for the carousel, keeping the headline order. - The rail ad comes from the feed ad placement, skipped for Plus, and logs impression, viewable impression and click. - Upvote, downvote, bookmark and copy link run the same mutations the feed cards use; post clicks log with a feed origin. - MainFeedLayout mounts it in the feed's own topContent slot on My feed and Popular, and tells the feed to stop inserting its Happening Now card so the headlines are not listed twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
A preview deploy is a production build, so GrowthBook devtools can't force `feed_hero` there and the section stays invisible for review. `?feed_hero=1` turns it on for that browser and remembers it, `?feed_hero=0` turns it back off. To be removed once the flag is configured in GrowthBook — a URL that opts someone into an experiment arm would skew the allocation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
Review feedback on the live feed: - Caps the section at 80rem and centres it; on a wide monitor it ran the full feed width. - The featured card's cover now fills its column, inset with its own corners like the feed cards, instead of being letterboxed over a blurred backdrop. Gated on `coverImage` so the in-feed wide cards keep the treatment they ship with. - Rebuilds the ad slot at the size of the two promo cards it replaces: a banner cover, then advertiser, title and tags. - Adds a `compact` mode to the highlights content for a surface with no card chrome: smaller heading, tighter rows, and a fade at the bottom of the scroll area so the last row isn't sliced by the pinned footer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
- The ad slot now runs advertiser, title, tags, then the cover, matching the order of the feed cards. - The featured card's summary was clamped at three lines, leaving a gap above the action row on a card that is much taller than a feed card. It runs to six in the hero, behind `expandDescription` so the in-feed wide cards keep the shorter clamp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
The carousel now rotates on its own. The active indicator fills over the slide's duration and the slide advances on that animation's `animationend`, so pausing the fill pauses the rotation: hovering or focusing anywhere in the hero freezes it mid-count and leaving resumes from the same point instead of restarting. Reduced motion drops the animation, which also stops the rotation. Only a change the reader asked for is announced, so an automatic rotation doesn't talk over a screen reader every few seconds. The paging arrows drop to the tertiary variant so they sit behind the content rather than beside it. In the rail, the ad, the highlight rows and "Read all" now share one text edge on both sides. The ad bleeds past it and is clipped by the column, so its hover surface reads as a full-width band like the rows above it, and the footer link goes flat instead of carrying its own inset pill. The ad's tracking pixel moves out of flow — it was a zero-size flex item still claiming a full gap — which, with a tighter column gap, closes most of the dead space between the ad and Happening Now. The hero and the rail get a little more room between them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
…ing Now The slide being replaced now stays mounted on top of the new one until its fade finishes, so the two cross over instead of the card popping. Measured in a browser, the pair never drops below full opacity mid-transition, and the outgoing slide unmounts on its own `animationend` — hence a near-zero duration under reduced motion rather than no animation at all, which would leave it mounted forever. The rail becomes one list: "Happening Now" heads the column and the ad is its first row, sharing the headlines' row treatment with the cover on the right at the cards' ratio. Reclaiming the space the stacked ad took brings the list from three visible headlines to five. The hero's cover grows to two thirds of the card, which leaves the text a third — narrow enough that the headline needed its own size, so `coverImage` and `expandDescription` collapse into one `hero` flag carrying the cover crop, the headline size and the summary clamp together. That split only holds where the text column can still hold a headline: below 1360px the hero falls back to an even split, which on a 1024px laptop is the difference between a full headline and a truncated one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
…eadline The cover was taking two thirds of the hero and squeezing the headline, so the wide cards gain a five-column span: the only ratio here where the text needs more than one column, hence a text-span map alongside the image one. Below 1360px the even split still stands. The ad drops into the Happening Now list as the second row rather than the first, so the freshest headline keeps the lead — and as the first row only when there are no headlines to sit under. It now carries a headline's shape: the copy on top, and the disclosure under it in the colour the rows give their timestamps, verified as the same computed value in both themes rather than by eye. The advertiser mark shrinks to the meta line's scale, the cover narrows, and the spacing around both opens up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
… card A five-line headline overran the hero's fixed-height card by about 7px, and `overflow: hidden` took the difference out of the action row, leaving a sliced strip of buttons along the bottom edge. The summary now gives way instead: it is the only shrinkable child, so the headline keeps every line and the actions keep their place. The opt-in is explicit because `base.css` resets everything to `flex-shrink: 0`, which is what let the overflow reach the actions rather than being absorbed higher up. Shrinking alone cut the last line mid-glyph, so the text block reserves a line of bottom padding under a matching fade: at full height the gradient covers only the padding and the last line stays solid, and once the block is squeezed the padding goes first and the cut line fades out. The padding sits on the block rather than the summary because `overflow: hidden` clips at the padding edge, which would leak a seventh line past the six-line clamp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
The rail gains a full-size direct placement below Happening Now, carrying the feed ad card's own design with its background and border removed so it sits on the page rather than in a box. Its inset goes with the chrome: the creative lines up with the headline rows above it instead of standing 16px inside them. The markup comes out of `AdGrid` into `AdCardContent` so both placements render one design rather than two copies. `AdGrid` keeps the card shell and the auto-rotation, which stays behind: the hero renders inside the feed's `ActiveFeedContext`, so rotating here would refetch against the feed's own ad cache and overwrite a slot the feed still owns. Each slot holds its own query key so the two ask the ad server separately and can come back with different creatives, and each logs its own impression, click and viewability under its own slot name. The rail now runs past the carousel rather than the two columns sharing one height, so the headline list keeps all five rows. The cost is dead space under the carousel, which grows with the card. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
…them The placement takes a column of its own to the right of Happening Now, so the section stays one row tall rather than the rail hanging past the carousel and leaving a few hundred pixels of dead space beside it. Three columns only fit from 1360px. Below that the ad would come out around 220px, narrow enough to push its "Remove" control off the end and to crowd the headline list, so that width keeps the two-column rail and sits the placement out; under `laptop` everything stacks and it returns at the end. The third column also takes about 200px off the carousel, which is enough that the 40/60 split stopped leaving the headline a readable column, so the card goes back to an even split whenever the ad column is up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
The hero drops its own width. The feed container already caps this box at the card grid's width, which tracks the reader's column count, so the fixed cap was both too wide at three columns and too narrow at five; without it the section measures exactly the grid beneath it. The rail's hover surfaces were bleeding past their column and being clipped by it, which squared off every corner they had. They now sit inside the column with the padding and the radius the feed cards use, so the shape under the cursor is a rounded card rather than a full-bleed band. The ad card takes the same treatment, and with the chrome back its content keeps the feed card's own inset — which retires the flush option added for the version that had none. More padding costs a row: the headline list shows four now rather than five. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
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.
Changes
Introduces a new hero section component for the feed that displays:
New Components
FeedHero: Container component that fetches headlines and featured posts, manages ad queries and event loggingFeedHeroSection: Layout wrapper combining carousel, highlights, and ad placementFeedHeroCarousel: Post carousel with indicator dots and prev/next navigationFeedHeroAd: Ad card optimized for the rail placementFeedSectionToolbar: Reusable toolbar for feed section headers (search, filters, bookmarks)PostTypeToListCard: Mapping of post types to list card components (mirrors existingPostTypeToWideCard)Integration
MainFeedLayoutfor My Feed and Popular pages whenfeatureFeedHeroflag is enableddisableHighlightCardsprop to prevent duplicate highlights when the hero section displays themFeature Flag
featureFeedHero: Controls hero section visibility on main feed pages (defaults to disabled)Manual Testing
https://claude.ai/code/session_01FWv8BuKdrX1GtDnSobxFAa
Preview domain
https://claude-hero-carousel-layout-e5e0.preview.app.daily.dev