Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/shared/src/components/FeedItemComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export type FeedItemComponentProps = {
/**
* When set, render the post as a wide featured highlight card spanning
* the given number of grid columns. Only used for article-like post
* types with an active `postHighlight`.
* types with an active `hero`.
*/
wideColSpan?: FeaturedWideColSpan;
} & Pick<UseVotePost, 'toggleUpvote' | 'toggleDownvote'> &
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import post from '../../../../__tests__/fixture/post';
import type { PostCardProps } from '../common/common';
import type {
Post,
PostHighlight,
PostHighlightSignificance,
PostHero,
PostHeroSignificance,
} from '../../../graphql/posts';
import { TestBootProvider } from '../../../../__tests__/helpers/boot';
import { ArticleFeaturedWideGridCard } from './ArticleFeaturedWideGridCard';
Expand Down Expand Up @@ -39,13 +39,10 @@ const defaultProps: PostCardProps = {
onReadArticleClick: jest.fn(),
};

const makeHighlight = (
significance: PostHighlightSignificance | null,
): PostHighlight | null =>
const makeHero = (significance: PostHeroSignificance | null): PostHero | null =>
significance
? {
id: 'h1',
channel: 'vibes',
highlightedAt: '2026-05-25T00:00:00.000Z',
headline: 'A breaking event',
significance,
Expand All @@ -61,12 +58,12 @@ const renderComponent = (
</TestBootProvider>,
);

const postWith = (significance: PostHighlightSignificance | null): Post => ({
const postWith = (significance: PostHeroSignificance | null): Post => ({
...post,
postHighlight: makeHighlight(significance),
hero: makeHero(significance),
});

it.each<[PostHighlightSignificance, string]>([
it.each<[PostHeroSignificance, string]>([
['breaking', 'Breaking'],
['major', 'Major'],
['notable', 'Notable'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useBlockPostPanel } from '../../../hooks/post/useBlockPostPanel';
import { useHiddenFeedbackPanel } from '../../../hooks/post/useHiddenFeedbackPanel';
import { usePostFeedback } from '../../../hooks';
import { isVideoPost, PostType } from '../../../graphql/posts';
import type { PostHighlightSignificance } from '../../../graphql/posts';
import type { PostHeroSignificance } from '../../../graphql/posts';
import { PostTagsPanel } from '../../post/block/PostTagsPanel';
import {
CardSpace,
Expand Down Expand Up @@ -45,17 +45,19 @@ const IMAGE_COL_SPAN: Record<FeaturedWideColSpan, string> = {
4: 'col-span-3',
};

const CHIP_LABEL: Partial<Record<PostHighlightSignificance, string>> = {
const CHIP_LABEL: Partial<Record<PostHeroSignificance, string>> = {
breaking: 'Breaking',
major: 'Major',
notable: 'Notable',
breakout: 'Breaking out',
evergreen: 'Evergreen',
};

const HighlightChip = ({
significance,
className,
}: {
significance: PostHighlightSignificance | null | undefined;
significance: PostHeroSignificance | null | undefined;
className?: string;
}): ReactElement | null => {
if (!significance) {
Expand Down Expand Up @@ -115,7 +117,7 @@ export const ArticleFeaturedWideGridCard = forwardRef(
const isVideoType = isVideoPost(post);
const image = usePostImage(post);
const { overlay } = useCardCover({ post, onShare });
const significance = post.postHighlight?.significance ?? null;
const significance = post.hero?.significance ?? null;
const isTweetPost =
post.type === PostType.SocialTwitter ||
post.sharedPost?.type === PostType.SocialTwitter;
Expand Down
5 changes: 2 additions & 3 deletions packages/shared/src/graphql/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,11 +696,10 @@ export const FEED_POST_FRAGMENT = gql`
name
}
}
postHighlight {
hero {
id
significance
headline
channel
significance
highlightedAt
}
}
Expand Down
13 changes: 13 additions & 0 deletions packages/shared/src/graphql/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ export type PostHighlightSignificance =
| 'notable'
| 'routine';

export type PostHeroSignificance =
| PostHighlightSignificance
| 'breakout'
| 'evergreen';

export interface PostHighlight {
id: string;
channel: string;
Expand Down Expand Up @@ -315,6 +320,14 @@ export interface Post {
liveRoom?: LiveRoomPost | null;
analytics?: Partial<Pick<PostAnalytics, 'impressions' | 'bookmarks'>>;
postHighlight?: PostHighlight | null;
hero?: PostHero | null;
}

export interface PostHero {
id: string;
headline: string;
significance: PostHeroSignificance;
highlightedAt: string;
}

export type RelatedPost = Pick<
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/hooks/feed/useLogImpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function useLogImpression(
if (item.type === 'post') {
const eventKey = generatePostLogEventKey(item.post.id);
if (inView && !item.post.impressionStatus) {
const significance = item.post.postHighlight?.significance;
const significance = item.post.hero?.significance;
logEventStart(
eventKey,
postLogEvent(LogEvent.Impression, item.post, {
Expand Down
11 changes: 5 additions & 6 deletions packages/shared/src/lib/feedHighlightColSpan.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { Ad, Post, PostHighlightSignificance } from '../graphql/posts';
import type { Ad, Post, PostHeroSignificance } from '../graphql/posts';
import { PostType } from '../graphql/posts';
import type { FeedItem } from '../hooks/useFeed';
import { FeedItemType } from '../components/cards/common/common';
import { computePlacements, requestedColSpan } from './feedHighlightColSpan';

const makePost = (
overrides: Partial<Post> & {
significance?: PostHighlightSignificance | null;
significance?: PostHeroSignificance | null;
} = {},
): Post => {
const { significance, ...rest } = overrides;
Expand All @@ -16,10 +16,9 @@ const makePost = (
image: '',
commentsPermalink: '',
...(significance !== undefined && {
postHighlight: significance
hero: significance
? {
id: 'h1',
channel: 'vibes',
highlightedAt: '2026-05-25T00:00:00.000Z',
headline: 'h',
significance,
Expand All @@ -46,11 +45,11 @@ const makeAdItem = (): FeedItem =>
} as FeedItem);

describe('requestedColSpan', () => {
it('returns 1 for items without postHighlight', () => {
it('returns 1 for items without hero', () => {
expect(requestedColSpan(makePostItem(makePost()))).toBe(1);
});

it.each<[PostHighlightSignificance, number]>([
it.each<[PostHeroSignificance, number]>([
['breaking', 4],
['major', 3],
['notable', 2],
Expand Down
10 changes: 6 additions & 4 deletions packages/shared/src/lib/feedHighlightColSpan.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { FeedItem } from '../hooks/useFeed';
import { FeedItemType } from '../components/cards/common/common';
import { PostType } from '../graphql/posts';
import type { PostHighlightSignificance } from '../graphql/posts';
import type { PostHeroSignificance } from '../graphql/posts';

const SIGNIFICANCE_COL_SPAN: Record<PostHighlightSignificance, number> = {
const SIGNIFICANCE_COL_SPAN: Record<PostHeroSignificance, number> = {
breaking: 4,
major: 3,
notable: 2,
routine: 1,
breakout: 4,
evergreen: 3,
};

const WIDENABLE_POST_TYPES = new Set<PostType>([
Expand All @@ -27,7 +29,7 @@ const LARGE_CARD_DENSITY = { maxLarge: 1, perItems: 10 } as const;
* Returns the column span a feed item is asking for, before any clamping
* for column count or fit-to-row.
*
* Only Post items with an article-like type and an active `postHighlight`
* Only Post items with an article-like type and an active `hero`
* request a wide colSpan. Ads, highlight strip items, placeholders,
* marketing items and non-article post types always stay at 1.
*/
Expand All @@ -40,7 +42,7 @@ export const requestedColSpan = (item: FeedItem): number => {
return 1;
}

const significance = item.post.postHighlight?.significance;
const significance = item.post.hero?.significance;
if (!significance) {
return 1;
}
Expand Down
Loading