Skip to content

Commit 159236c

Browse files
committed
Pass a unique card ID down to Card component in flexible containers
1 parent 2601eaf commit 159236c

File tree

6 files changed

+116
-75
lines changed

6 files changed

+116
-75
lines changed

dotcom-rendering/src/components/Card/Card.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ export type Props = {
9696
avatarUrl?: string;
9797
showClock?: boolean;
9898
mainMedia?: MainMedia;
99-
/** Note YouTube recommends a minimum width of 480px @see https://developers.google.com/youtube/terms/required-minimum-functionality#embedded-youtube-player-size
99+
/**
100+
* Note YouTube recommends a minimum width of 480px @see https://developers.google.com/youtube/terms/required-minimum-functionality#embedded-youtube-player-size
100101
* At 300px or below, the player will begin to lose functionality e.g. volume controls being omitted.
101102
* Youtube requires a minimum width 200px.
102103
*/
@@ -133,8 +134,14 @@ export type Props = {
133134
isTagPage?: boolean;
134135
/** Allows the consumer to set an aspect ratio on the image of 5:3, 5:4, 4:5 or 1:1 */
135136
aspectRatio?: AspectRatio;
137+
/** The index of the card in a carousel */
136138
index?: number;
137-
/** The Splash card in a flexible container gets a different visual treatment to other cards*/
139+
/**
140+
* Useful for videos. Has the form: collection-{collection ID}-{card grouping type}-{card index}
141+
* For example, the first splash card in the second collection would be: "collection-1-splash-0"
142+
*/
143+
uniqueId?: string;
144+
/** The Splash card in a flexible container gets a different visual treatment to other cards */
138145
isFlexSplash?: boolean;
139146
showTopBarDesktop?: boolean;
140147
showTopBarMobile?: boolean;
@@ -402,6 +409,7 @@ export const Card = ({
402409
isTagPage = false,
403410
aspectRatio,
404411
index = 0,
412+
uniqueId = '',
405413
isFlexSplash,
406414
showTopBarDesktop = true,
407415
showTopBarMobile = true,

dotcom-rendering/src/components/DecideContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export const DecideContainer = ({
6464
collectionId,
6565
containerLevel,
6666
}: Props) => {
67-
// If you add a new container type which contains an MPU, you must also add it to
6867
switch (containerType) {
6968
case 'dynamic/fast':
7069
return (
@@ -255,6 +254,7 @@ export const DecideContainer = ({
255254
absoluteServerTimes={absoluteServerTimes}
256255
imageLoading={imageLoading}
257256
aspectRatio={aspectRatio}
257+
collectionId={collectionId}
258258
/>
259259
);
260260
case 'flexible/general':

dotcom-rendering/src/components/FlexibleGeneral.tsx

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ export const decideCardPositions = (cards: DCRFrontCard[]): GroupedCards => {
8080
}, []);
8181
};
8282

83+
type ImmersiveCardLayoutProps = {
84+
card: DCRFrontCard;
85+
containerPalette?: DCRContainerPalette;
86+
absoluteServerTimes: boolean;
87+
imageLoading: Loading;
88+
collectionId: number;
89+
};
90+
8391
/**
8492
* ImmersiveCardLayout is a special case of the card layout that is used for cards with the isImmersive property.
8593
* It is a single feature card that takes up the full width of the container on all breakpoints.
@@ -92,13 +100,7 @@ const ImmersiveCardLayout = ({
92100
absoluteServerTimes,
93101
imageLoading,
94102
collectionId,
95-
}: {
96-
card: DCRFrontCard;
97-
containerPalette?: DCRContainerPalette;
98-
absoluteServerTimes: boolean;
99-
imageLoading: Loading;
100-
collectionId: number;
101-
}) => {
103+
}: ImmersiveCardLayoutProps) => {
102104
const isLoopingVideo = card.mainMedia?.type === 'LoopVideo';
103105

104106
return (
@@ -229,6 +231,18 @@ const decideSplashCardProperties = (
229231
}
230232
};
231233

234+
type SplashCardLayoutProps = {
235+
cards: DCRFrontCard[];
236+
imageLoading: Loading;
237+
containerPalette?: DCRContainerPalette;
238+
showAge?: boolean;
239+
absoluteServerTimes: boolean;
240+
aspectRatio: AspectRatio;
241+
isLastRow: boolean;
242+
containerLevel: DCRContainerLevel;
243+
collectionId: number;
244+
};
245+
232246
const SplashCardLayout = ({
233247
cards,
234248
containerPalette,
@@ -239,17 +253,7 @@ const SplashCardLayout = ({
239253
isLastRow,
240254
containerLevel,
241255
collectionId,
242-
}: {
243-
cards: DCRFrontCard[];
244-
imageLoading: Loading;
245-
containerPalette?: DCRContainerPalette;
246-
showAge?: boolean;
247-
absoluteServerTimes: boolean;
248-
aspectRatio: AspectRatio;
249-
isLastRow: boolean;
250-
containerLevel: DCRContainerLevel;
251-
collectionId: number;
252-
}) => {
256+
}: SplashCardLayoutProps) => {
253257
const card = cards[0];
254258
if (!card) return null;
255259

@@ -380,6 +384,19 @@ const decideCardProperties = (
380384
}
381385
};
382386

387+
type FullWidthCardLayoutProps = {
388+
cards: DCRFrontCard[];
389+
imageLoading: Loading;
390+
containerPalette?: DCRContainerPalette;
391+
showAge?: boolean;
392+
absoluteServerTimes: boolean;
393+
aspectRatio: AspectRatio;
394+
isFirstRow: boolean;
395+
isLastRow: boolean;
396+
containerLevel: DCRContainerLevel;
397+
collectionId: number;
398+
};
399+
383400
const FullWidthCardLayout = ({
384401
cards,
385402
containerPalette,
@@ -391,18 +408,7 @@ const FullWidthCardLayout = ({
391408
isLastRow,
392409
containerLevel,
393410
collectionId,
394-
}: {
395-
cards: DCRFrontCard[];
396-
imageLoading: Loading;
397-
containerPalette?: DCRContainerPalette;
398-
showAge?: boolean;
399-
absoluteServerTimes: boolean;
400-
aspectRatio: AspectRatio;
401-
isFirstRow: boolean;
402-
isLastRow: boolean;
403-
containerLevel: DCRContainerLevel;
404-
collectionId: number;
405-
}) => {
411+
}: FullWidthCardLayoutProps) => {
406412
const card = cards[0];
407413
if (!card) return null;
408414

@@ -481,6 +487,20 @@ const FullWidthCardLayout = ({
481487
);
482488
};
483489

490+
type HalfWidthCardLayoutProps = {
491+
cards: DCRFrontCard[];
492+
imageLoading: Loading;
493+
isFirstRow?: boolean;
494+
isFirstStandardRow?: boolean;
495+
containerPalette?: DCRContainerPalette;
496+
showAge?: boolean;
497+
absoluteServerTimes: boolean;
498+
aspectRatio: AspectRatio;
499+
row: number;
500+
isLastRow: boolean;
501+
containerLevel: DCRContainerLevel;
502+
};
503+
484504
const HalfWidthCardLayout = ({
485505
cards,
486506
containerPalette,
@@ -493,19 +513,7 @@ const HalfWidthCardLayout = ({
493513
row,
494514
isLastRow,
495515
containerLevel,
496-
}: {
497-
cards: DCRFrontCard[];
498-
imageLoading: Loading;
499-
isFirstRow?: boolean;
500-
isFirstStandardRow?: boolean;
501-
containerPalette?: DCRContainerPalette;
502-
showAge?: boolean;
503-
absoluteServerTimes: boolean;
504-
aspectRatio: AspectRatio;
505-
row: number;
506-
isLastRow: boolean;
507-
containerLevel: DCRContainerLevel;
508-
}) => {
516+
}: HalfWidthCardLayoutProps) => {
509517
if (cards.length === 0) return null;
510518

511519
return (
@@ -577,8 +585,16 @@ export const FlexibleGeneral = ({
577585
containerLevel = 'Primary',
578586
collectionId,
579587
}: Props) => {
580-
const splash = [...groupedTrails.splash].slice(0, 1);
581-
const cards = [...groupedTrails.standard].slice(0, 19);
588+
const splash = [...groupedTrails.splash].slice(0, 1).map((snap) => ({
589+
...snap,
590+
uniqueId: `collection-${collectionId}-splash-0`,
591+
}));
592+
const cards = [...groupedTrails.standard]
593+
.slice(0, 19)
594+
.map((standard, i) => ({
595+
...standard,
596+
uniqueId: `collection-${collectionId}-standard-${i}`,
597+
}));
582598
const groupedCards = decideCardPositions(cards);
583599

584600
return (

dotcom-rendering/src/components/FlexibleSpecial.tsx

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type Props = {
2626
absoluteServerTimes: boolean;
2727
aspectRatio: AspectRatio;
2828
containerLevel?: DCRContainerLevel;
29+
collectionId: number;
2930
};
3031

3132
type BoostProperties = {
@@ -106,6 +107,18 @@ const determineCardProperties = (
106107
}
107108
};
108109

110+
type OneCardLayoutProps = {
111+
cards: DCRFrontCard[];
112+
imageLoading: Loading;
113+
containerPalette?: DCRContainerPalette;
114+
showAge?: boolean;
115+
absoluteServerTimes: boolean;
116+
aspectRatio: AspectRatio;
117+
isLastRow: boolean;
118+
isFirstRow: boolean;
119+
containerLevel: DCRContainerLevel;
120+
};
121+
109122
export const OneCardLayout = ({
110123
cards,
111124
containerPalette,
@@ -116,17 +129,7 @@ export const OneCardLayout = ({
116129
isLastRow,
117130
isFirstRow,
118131
containerLevel,
119-
}: {
120-
cards: DCRFrontCard[];
121-
imageLoading: Loading;
122-
containerPalette?: DCRContainerPalette;
123-
showAge?: boolean;
124-
absoluteServerTimes: boolean;
125-
aspectRatio: AspectRatio;
126-
isLastRow: boolean;
127-
isFirstRow: boolean;
128-
containerLevel: DCRContainerLevel;
129-
}) => {
132+
}: OneCardLayoutProps) => {
130133
const card = cards[0];
131134
if (!card) return null;
132135

@@ -191,17 +194,7 @@ const getImagePosition = (
191194
return 'bottom';
192195
};
193196

194-
const TwoCardOrFourCardLayout = ({
195-
cards,
196-
containerPalette,
197-
showAge,
198-
absoluteServerTimes,
199-
showImage = true,
200-
imageLoading,
201-
aspectRatio,
202-
isFirstRow,
203-
containerLevel,
204-
}: {
197+
type TwoOrFourCardLayoutProps = {
205198
cards: DCRFrontCard[];
206199
imageLoading: Loading;
207200
containerPalette?: DCRContainerPalette;
@@ -211,7 +204,19 @@ const TwoCardOrFourCardLayout = ({
211204
aspectRatio: AspectRatio;
212205
isFirstRow: boolean;
213206
containerLevel: DCRContainerLevel;
214-
}) => {
207+
};
208+
209+
const TwoOrFourCardLayout = ({
210+
cards,
211+
containerPalette,
212+
showAge,
213+
absoluteServerTimes,
214+
showImage = true,
215+
imageLoading,
216+
aspectRatio,
217+
isFirstRow,
218+
containerLevel,
219+
}: TwoOrFourCardLayoutProps) => {
215220
if (cards.length === 0) return null;
216221
const hasTwoOrFewerCards = cards.length <= 2;
217222

@@ -267,10 +272,20 @@ export const FlexibleSpecial = ({
267272
imageLoading,
268273
aspectRatio,
269274
containerLevel = 'Primary',
275+
collectionId,
270276
}: Props) => {
271-
const snaps = [...groupedTrails.snap].slice(0, 1);
272-
const splash = [...groupedTrails.standard].slice(0, 1);
273-
const cards = [...groupedTrails.standard].slice(1, 5);
277+
const snaps = [...groupedTrails.snap].slice(0, 1).map((snap) => ({
278+
...snap,
279+
uniqueId: `collection-${collectionId}-snap-0`,
280+
}));
281+
const splash = [...groupedTrails.standard].slice(0, 1).map((snap) => ({
282+
...snap,
283+
uniqueId: `collection-${collectionId}-splash-0`,
284+
}));
285+
const cards = [...groupedTrails.standard].slice(1, 5).map((snap, i) => ({
286+
...snap,
287+
uniqueId: `collection-${collectionId}-standard-${i}`,
288+
}));
274289

275290
return (
276291
<>
@@ -296,7 +311,7 @@ export const FlexibleSpecial = ({
296311
isFirstRow={!isNonEmptyArray(snaps)}
297312
containerLevel={containerLevel}
298313
/>
299-
<TwoCardOrFourCardLayout
314+
<TwoOrFourCardLayout
300315
cards={cards}
301316
containerPalette={containerPalette}
302317
showAge={showAge}

dotcom-rendering/src/components/FrontCard.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export const FrontCard = (props: Props) => {
5656
slideshowImages: trail.slideshowImages,
5757
showLivePlayable: trail.showLivePlayable,
5858
showVideo: trail.showVideo,
59+
uniqueId: trail.uniqueId,
5960
};
6061

6162
return Card({ ...defaultProps, ...cardProps });

dotcom-rendering/src/types/front.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export type DCRFrontCard = {
102102
branding?: Branding;
103103
slideshowImages?: DCRSlideshowImage[];
104104
showVideo?: boolean;
105+
uniqueId?: string;
105106
};
106107

107108
export type DCRSlideshowImage = {

0 commit comments

Comments
 (0)