Skip to content

Commit 42236e6

Browse files
authored
Merge pull request #14969 from guardian/doml/refactor-feature-card-video
Refactor Feature Card video
2 parents 39a4669 + ae9dfc3 commit 42236e6

File tree

8 files changed

+85
-133
lines changed

8 files changed

+85
-133
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ const wideIconStyles = (
4343
}
4444
`;
4545

46-
export const narrowPlayIconWidth = 56;
46+
export const narrowPlayIconDiameter = 56;
4747
const narrowStyles = css`
48-
width: ${narrowPlayIconWidth}px;
49-
height: ${narrowPlayIconWidth}px;
48+
width: ${narrowPlayIconDiameter}px;
49+
height: ${narrowPlayIconDiameter}px;
5050
display: flex;
5151
justify-content: center;
5252
align-items: center;

dotcom-rendering/src/components/FeatureCard.stories.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export const YoutubeVideo = {
291291
design: ArticleDesign.Video,
292292
},
293293
image: {
294-
src: 'https://media.guim.co.uk/f2aedd24e5414073a653f68112e0ad070c6f4a2b/254_0_7493_4500/master/7493.jpg',
294+
src: 'https://media.guim.co.uk/7b500cfe9afe4e211ad771c86e66297c9c22993b/0_61_4801_2880/master/4801.jpg',
295295
altText: 'alt text',
296296
},
297297
mainMedia: {
@@ -338,6 +338,20 @@ export const YoutubeVideoMainMediaImmersive = {
338338
},
339339
} satisfies Story;
340340

341+
export const YoutubeVideoCannotPlayInline = {
342+
args: {
343+
...YoutubeVideo.args,
344+
canPlayInline: false,
345+
},
346+
} satisfies Story;
347+
348+
export const YoutubeVideoMainMediaCannotPlayInline = {
349+
args: {
350+
...YoutubeVideoMainMedia.args,
351+
canPlayInline: false,
352+
},
353+
} satisfies Story;
354+
341355
export const WithTrailText = {
342356
args: {
343357
kickerText: undefined,

dotcom-rendering/src/components/FeatureCard.tsx

Lines changed: 61 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ import type {
2424
DCRFrontImage,
2525
DCRSupportingContent,
2626
} from '../types/front';
27-
import type { MainMedia } from '../types/mainMedia';
27+
import type { MainMedia, YoutubeVideo } from '../types/mainMedia';
2828
import { BrandingLabel } from './BrandingLabel';
2929
import { CardFooter } from './Card/components/CardFooter';
3030
import { CardLink } from './Card/components/CardLink';
3131
import type { MediaSizeType } from './Card/components/MediaWrapper';
32+
import { narrowPlayIconDiameter, PlayIcon } from './Card/components/PlayIcon';
3233
import { TrailText } from './Card/components/TrailText';
3334
import { CardHeadline, type ResponsiveFontSize } from './CardHeadline';
3435
import type { Loading } from './CardPicture';
@@ -38,7 +39,6 @@ import { FeatureCardCardAge } from './FeatureCardCardAge';
3839
import { FeatureCardCommentCount } from './FeatureCardCommentCount';
3940
import { FormatBoundary } from './FormatBoundary';
4041
import { Island } from './Island';
41-
import { MediaDuration } from './MediaDuration';
4242
import { Pill } from './Pill';
4343
import { StarRating } from './StarRating/StarRating';
4444
import { SupportingContent } from './SupportingContent';
@@ -47,6 +47,17 @@ import { YoutubeBlockComponent } from './YoutubeBlockComponent.importable';
4747

4848
export type Position = 'inner' | 'outer' | 'none';
4949

50+
type Media =
51+
| {
52+
type: 'picture';
53+
imageUrl: string;
54+
imageAltText?: string;
55+
}
56+
| {
57+
type: 'youtube-video';
58+
mainMedia: YoutubeVideo;
59+
};
60+
5061
const baseCardStyles = css`
5162
display: flex;
5263
flex-direction: column;
@@ -224,6 +235,12 @@ const videoPillStyles = css`
224235
right: ${space[2]}px;
225236
`;
226237

238+
const playIconStyles = css`
239+
position: absolute;
240+
top: calc(50% - ${narrowPlayIconDiameter / 2}px);
241+
left: calc(50% - ${narrowPlayIconDiameter / 2}px);
242+
`;
243+
227244
const waveformStyles = css`
228245
position: absolute;
229246
bottom: 0;
@@ -239,16 +256,16 @@ const getMedia = ({
239256
imageUrl,
240257
imageAltText,
241258
mainMedia,
242-
canPlayInline,
259+
showVideo,
243260
}: {
244261
imageUrl?: string;
245262
imageAltText?: string;
246263
mainMedia?: MainMedia;
247-
canPlayInline?: boolean;
248-
}) => {
249-
if (mainMedia && mainMedia.type === 'YoutubeVideo' && canPlayInline) {
264+
showVideo?: boolean;
265+
}): Media | undefined => {
266+
if (mainMedia?.type === 'YoutubeVideo' && showVideo) {
250267
return {
251-
type: 'video',
268+
type: 'youtube-video',
252269
mainMedia,
253270
} as const;
254271
}
@@ -358,7 +375,7 @@ export const FeatureCard = ({
358375
imageLoading,
359376
showClock,
360377
mainMedia,
361-
canPlayInline,
378+
canPlayInline = false,
362379
kickerText,
363380
showPulsingDot,
364381
dataLinkName,
@@ -380,22 +397,15 @@ export const FeatureCard = ({
380397
}: Props) => {
381398
const hasSublinks = supportingContent && supportingContent.length > 0;
382399

383-
const isVideoMainMedia = mainMedia?.type === 'YoutubeVideo';
384400
const isVideoArticle = format.design === ArticleDesign.Video;
385401

386-
const videoDuration =
387-
mainMedia?.type === 'YoutubeVideo' ? mainMedia.duration : undefined;
388-
389402
const media = getMedia({
390403
imageUrl: image?.src,
391404
imageAltText: image?.altText,
392405
mainMedia,
393-
canPlayInline,
406+
showVideo: showVideo && canPlayInline,
394407
});
395408

396-
const showYoutubeVideo =
397-
canPlayInline && showVideo && mainMedia?.type === 'YoutubeVideo';
398-
399409
const showCardAge =
400410
webPublicationDate !== undefined && showClock !== undefined;
401411

@@ -410,11 +420,13 @@ export const FeatureCard = ({
410420

411421
const isLabs = format.theme === ArticleSpecial.Labs;
412422

423+
if (!media) return null;
424+
413425
return (
414426
<FormatBoundary format={format}>
415427
<ContainerOverrides containerPalette={containerPalette}>
416428
<div css={[baseCardStyles, hoverStyles, sublinkHoverStyles]}>
417-
{!showYoutubeVideo && (
429+
{media.type !== 'youtube-video' && (
418430
<CardLink
419431
linkTo={linkTo}
420432
headlineText={headlineText}
@@ -423,7 +435,7 @@ export const FeatureCard = ({
423435
/>
424436
)}
425437
<div css={contentStyles}>
426-
{showYoutubeVideo && (
438+
{media.type === 'youtube-video' && (
427439
<div
428440
data-chromatic="ignore"
429441
data-component="youtube-atom"
@@ -438,15 +450,15 @@ export const FeatureCard = ({
438450
defer={{ until: 'visible' }}
439451
>
440452
<YoutubeBlockComponent
441-
id={mainMedia.id}
442-
assetId={mainMedia.videoId}
453+
id={media.mainMedia.id}
454+
assetId={media.mainMedia.videoId}
443455
index={collectionId}
444-
expired={mainMedia.expired}
456+
expired={media.mainMedia.expired}
445457
format={format}
446458
stickyVideos={false}
447459
enableAds={false}
448-
duration={mainMedia.duration}
449-
posterImage={mainMedia.image}
460+
duration={media.mainMedia.duration}
461+
posterImage={media.mainMedia.image}
450462
width={300}
451463
height={375}
452464
origin="The Guardian"
@@ -478,7 +490,7 @@ export const FeatureCard = ({
478490
</Island>
479491
</div>
480492
)}
481-
{!showYoutubeVideo && media && (
493+
{media.type !== 'youtube-video' && (
482494
<div
483495
css={css`
484496
position: relative;
@@ -487,23 +499,7 @@ export const FeatureCard = ({
487499
)};
488500
`}
489501
>
490-
{media.type === 'video' && (
491-
<div>
492-
<CardPicture
493-
mainImage={
494-
media.mainMedia.image ?? ''
495-
}
496-
imageSize={imageSize}
497-
alt={headlineText}
498-
loading={imageLoading}
499-
aspectRatio={aspectRatio}
500-
mobileAspectRatio={
501-
mobileAspectRatio
502-
}
503-
/>
504-
</div>
505-
)}
506-
502+
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- A PR to add self-hosted video is upcoming where this check will be needed. */}
507503
{media.type === 'picture' && (
508504
<>
509505
<CardPicture
@@ -516,20 +512,30 @@ export const FeatureCard = ({
516512
mobileAspectRatio
517513
}
518514
/>
519-
{isVideoMainMedia &&
520-
mainMedia.duration > 0 && (
521-
<MediaDuration
522-
mediaDuration={
523-
mainMedia.duration
524-
}
525-
mediaPositionOnDesktop={
526-
'top'
527-
}
528-
mediaPositionOnMobile={
529-
'left'
530-
}
531-
/>
532-
)}
515+
516+
{mainMedia?.type === 'YoutubeVideo' && (
517+
<>
518+
{mainMedia.duration > 0 && (
519+
<div css={videoPillStyles}>
520+
<Pill
521+
content={
522+
<time>
523+
{secondsToDuration(
524+
mainMedia.duration,
525+
)}
526+
</time>
527+
}
528+
icon={
529+
<SvgMediaControlsPlay />
530+
}
531+
/>
532+
</div>
533+
)}
534+
<div css={playIconStyles}>
535+
<PlayIcon iconWidth="narrow" />
536+
</div>
537+
</>
538+
)}
533539
</>
534540
)}
535541

@@ -678,7 +684,6 @@ export const FeatureCard = ({
678684
) : undefined
679685
}
680686
showLivePlayable={false}
681-
mainMedia={mainMedia}
682687
isNewsletter={isNewsletter}
683688
/>
684689

@@ -689,23 +694,6 @@ export const FeatureCard = ({
689694
233,
690695
)}
691696
</div>
692-
{/* On video article cards, the duration is displayed in the footer */}
693-
{!isVideoArticle &&
694-
isVideoMainMedia &&
695-
videoDuration !== undefined ? (
696-
<div css={videoPillStyles}>
697-
<Pill
698-
content={
699-
<time>
700-
{secondsToDuration(
701-
videoDuration,
702-
)}
703-
</time>
704-
}
705-
icon={<SvgMediaControlsPlay />}
706-
/>
707-
</div>
708-
) : null}
709697
</div>
710698

711699
{isImmersive &&

dotcom-rendering/src/components/MediaDuration.tsx

Lines changed: 0 additions & 49 deletions
This file was deleted.

dotcom-rendering/src/components/SelfHostedVideoPlayer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { ActiveCue } from '../lib/useSubtitles';
1717
import { filterOutHlsSources, type Source } from '../lib/video';
1818
import { palette } from '../palette';
1919
import type { VideoPlayerFormat } from '../types/mainMedia';
20-
import { narrowPlayIconWidth, PlayIcon } from './Card/components/PlayIcon';
20+
import { narrowPlayIconDiameter, PlayIcon } from './Card/components/PlayIcon';
2121
import { SubtitleOverlay } from './SubtitleOverlay';
2222
import { VideoProgressBar } from './VideoProgressBar';
2323

@@ -50,8 +50,8 @@ const subtitleStyles = (subtitleSize: SubtitleSize | undefined) => css`
5050
const playIconStyles = css`
5151
position: absolute;
5252
/* Center the icon */
53-
top: calc(50% - ${narrowPlayIconWidth / 2}px);
54-
left: calc(50% - ${narrowPlayIconWidth / 2}px);
53+
top: calc(50% - ${narrowPlayIconDiameter / 2}px);
54+
left: calc(50% - ${narrowPlayIconDiameter / 2}px);
5555
cursor: pointer;
5656
border: none;
5757
background: none;

dotcom-rendering/src/components/StaticFeatureTwo.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ export const StaticFeatureTwo = ({
7171
isExternalLink={card.isExternalLink}
7272
branding={card.branding}
7373
containerPalette={containerPalette}
74-
trailText={undefined}
7574
serverTime={serverTime}
7675
imageLoading={imageLoading}
7776
aspectRatio={aspectRatio}

0 commit comments

Comments
 (0)