@@ -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' ;
2828import { BrandingLabel } from './BrandingLabel' ;
2929import { CardFooter } from './Card/components/CardFooter' ;
3030import { CardLink } from './Card/components/CardLink' ;
3131import type { MediaSizeType } from './Card/components/MediaWrapper' ;
32+ import { narrowPlayIconDiameter , PlayIcon } from './Card/components/PlayIcon' ;
3233import { TrailText } from './Card/components/TrailText' ;
3334import { CardHeadline , type ResponsiveFontSize } from './CardHeadline' ;
3435import type { Loading } from './CardPicture' ;
@@ -38,7 +39,6 @@ import { FeatureCardCardAge } from './FeatureCardCardAge';
3839import { FeatureCardCommentCount } from './FeatureCardCommentCount' ;
3940import { FormatBoundary } from './FormatBoundary' ;
4041import { Island } from './Island' ;
41- import { MediaDuration } from './MediaDuration' ;
4242import { Pill } from './Pill' ;
4343import { StarRating } from './StarRating/StarRating' ;
4444import { SupportingContent } from './SupportingContent' ;
@@ -47,6 +47,17 @@ import { YoutubeBlockComponent } from './YoutubeBlockComponent.importable';
4747
4848export 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+
5061const 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+
227244const 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 &&
0 commit comments