Skip to content

Commit 3dca227

Browse files
committed
Refactor Feature card Youtube video
1 parent bfadeae commit 3dca227

File tree

7 files changed

+72
-82
lines changed

7 files changed

+72
-82
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export const YoutubeVideo = {
292292
design: ArticleDesign.Video,
293293
},
294294
image: {
295-
src: 'https://media.guim.co.uk/f2aedd24e5414073a653f68112e0ad070c6f4a2b/254_0_7493_4500/master/7493.jpg',
295+
src: 'https://media.guim.co.uk/7b500cfe9afe4e211ad771c86e66297c9c22993b/0_61_4801_2880/master/4801.jpg',
296296
altText: 'alt text',
297297
},
298298
mainMedia: {

dotcom-rendering/src/components/FeatureCard.tsx

Lines changed: 62 additions & 71 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,18 @@ const getMedia = ({
239256
imageUrl,
240257
imageAltText,
241258
mainMedia,
242-
canPlayInline,
259+
isVideoArticle,
260+
showVideo,
243261
}: {
244262
imageUrl?: string;
245263
imageAltText?: string;
246264
mainMedia?: MainMedia;
247-
canPlayInline?: boolean;
248-
}) => {
249-
if (mainMedia && mainMedia.type === 'YoutubeVideo' && canPlayInline) {
265+
isVideoArticle: boolean;
266+
showVideo?: boolean;
267+
}): Media | undefined => {
268+
if (isVideoArticle && mainMedia?.type === 'YoutubeVideo' && showVideo) {
250269
return {
251-
type: 'video',
270+
type: 'youtube-video',
252271
mainMedia,
253272
} as const;
254273
}
@@ -360,7 +379,7 @@ export const FeatureCard = ({
360379
imageLoading,
361380
showClock,
362381
mainMedia,
363-
canPlayInline,
382+
canPlayInline = false,
364383
kickerText,
365384
showPulsingDot,
366385
dataLinkName,
@@ -383,22 +402,16 @@ export const FeatureCard = ({
383402
}: Props) => {
384403
const hasSublinks = supportingContent && supportingContent.length > 0;
385404

386-
const isVideoMainMedia = mainMedia?.type === 'YoutubeVideo';
387405
const isVideoArticle = format.design === ArticleDesign.Video;
388406

389-
const videoDuration =
390-
mainMedia?.type === 'YoutubeVideo' ? mainMedia.duration : undefined;
391-
392407
const media = getMedia({
393408
imageUrl: image?.src,
394409
imageAltText: image?.altText,
395410
mainMedia,
396-
canPlayInline,
411+
isVideoArticle,
412+
showVideo: showVideo && canPlayInline,
397413
});
398414

399-
const showYoutubeVideo =
400-
canPlayInline && showVideo && mainMedia?.type === 'YoutubeVideo';
401-
402415
const showCardAge =
403416
webPublicationDate !== undefined && showClock !== undefined;
404417

@@ -413,11 +426,13 @@ export const FeatureCard = ({
413426

414427
const isLabs = format.theme === ArticleSpecial.Labs;
415428

429+
if (!media) return null;
430+
416431
return (
417432
<FormatBoundary format={format}>
418433
<ContainerOverrides containerPalette={containerPalette}>
419434
<div css={[baseCardStyles, hoverStyles, sublinkHoverStyles]}>
420-
{!showYoutubeVideo && (
435+
{media.type !== 'youtube-video' && (
421436
<CardLink
422437
linkTo={linkTo}
423438
headlineText={headlineText}
@@ -426,7 +441,7 @@ export const FeatureCard = ({
426441
/>
427442
)}
428443
<div css={contentStyles}>
429-
{showYoutubeVideo && (
444+
{media.type === 'youtube-video' && (
430445
<div
431446
data-chromatic="ignore"
432447
data-component="youtube-atom"
@@ -441,15 +456,15 @@ export const FeatureCard = ({
441456
defer={{ until: 'visible' }}
442457
>
443458
<YoutubeBlockComponent
444-
id={mainMedia.id}
445-
assetId={mainMedia.videoId}
459+
id={media.mainMedia.id}
460+
assetId={media.mainMedia.videoId}
446461
index={collectionId}
447-
expired={mainMedia.expired}
462+
expired={media.mainMedia.expired}
448463
format={format}
449464
stickyVideos={false}
450465
enableAds={false}
451-
duration={mainMedia.duration}
452-
posterImage={mainMedia.image}
466+
duration={media.mainMedia.duration}
467+
posterImage={media.mainMedia.image}
453468
width={300}
454469
height={375}
455470
origin="The Guardian"
@@ -481,7 +496,7 @@ export const FeatureCard = ({
481496
</Island>
482497
</div>
483498
)}
484-
{!showYoutubeVideo && media && (
499+
{media.type !== 'youtube-video' && (
485500
<div
486501
css={css`
487502
position: relative;
@@ -490,23 +505,7 @@ export const FeatureCard = ({
490505
)};
491506
`}
492507
>
493-
{media.type === 'video' && (
494-
<div>
495-
<CardPicture
496-
mainImage={
497-
media.mainMedia.image ?? ''
498-
}
499-
imageSize={imageSize}
500-
alt={headlineText}
501-
loading={imageLoading}
502-
aspectRatio={aspectRatio}
503-
mobileAspectRatio={
504-
mobileAspectRatio
505-
}
506-
/>
507-
</div>
508-
)}
509-
508+
{/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- A PR to add self-hosted video is upcoming where this check will be needed. */}
510509
{media.type === 'picture' && (
511510
<>
512511
<CardPicture
@@ -519,20 +518,30 @@ export const FeatureCard = ({
519518
mobileAspectRatio
520519
}
521520
/>
522-
{isVideoMainMedia &&
521+
522+
{mainMedia?.type === 'YoutubeVideo' &&
523523
mainMedia.duration > 0 && (
524-
<MediaDuration
525-
mediaDuration={
526-
mainMedia.duration
527-
}
528-
mediaPositionOnDesktop={
529-
'top'
530-
}
531-
mediaPositionOnMobile={
532-
'left'
533-
}
534-
/>
524+
<div css={videoPillStyles}>
525+
<Pill
526+
content={
527+
<time>
528+
{secondsToDuration(
529+
mainMedia.duration,
530+
)}
531+
</time>
532+
}
533+
icon={
534+
<SvgMediaControlsPlay />
535+
}
536+
/>
537+
</div>
535538
)}
539+
540+
{mainMedia?.type === 'YoutubeVideo' && (
541+
<div css={playIconStyles}>
542+
<PlayIcon iconWidth="narrow" />
543+
</div>
544+
)}
536545
</>
537546
)}
538547

@@ -684,7 +693,6 @@ export const FeatureCard = ({
684693
) : undefined
685694
}
686695
showLivePlayable={false}
687-
mainMedia={mainMedia}
688696
isNewsletter={isNewsletter}
689697
/>
690698

@@ -695,23 +703,6 @@ export const FeatureCard = ({
695703
233,
696704
)}
697705
</div>
698-
{/* On video article cards, the duration is displayed in the footer */}
699-
{!isVideoArticle &&
700-
isVideoMainMedia &&
701-
videoDuration !== undefined ? (
702-
<div css={videoPillStyles}>
703-
<Pill
704-
content={
705-
<time>
706-
{secondsToDuration(
707-
videoDuration,
708-
)}
709-
</time>
710-
}
711-
icon={<SvgMediaControlsPlay />}
712-
/>
713-
</div>
714-
) : null}
715706
</div>
716707

717708
{isImmersive &&

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
@@ -74,7 +74,6 @@ export const StaticFeatureTwo = ({
7474
isExternalLink={card.isExternalLink}
7575
branding={card.branding}
7676
containerPalette={containerPalette}
77-
trailText={undefined}
7877
serverTime={serverTime}
7978
imageLoading={imageLoading}
8079
aspectRatio={aspectRatio}

dotcom-rendering/src/components/YoutubeAtom/YoutubeAtomFeatureCardOverlay.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { transparentColour } from '../../lib/transparentColour';
1111
import { palette } from '../../palette';
1212
import type { AspectRatio } from '../../types/front';
1313
import { CardFooter } from '../Card/components/CardFooter';
14-
import { narrowPlayIconWidth, PlayIcon } from '../Card/components/PlayIcon';
14+
import { narrowPlayIconDiameter, PlayIcon } from '../Card/components/PlayIcon';
1515
import { TrailText } from '../Card/components/TrailText';
1616
import type { ResponsiveFontSize } from '../CardHeadline';
1717
import { CardHeadline } from '../CardHeadline';
@@ -106,7 +106,7 @@ const playIconStyles = css`
106106
* headlines and standfirsts before we decide on a final position.
107107
*/
108108
top: 35%;
109-
left: calc(50% - ${narrowPlayIconWidth / 2}px);
109+
left: calc(50% - ${narrowPlayIconDiameter / 2}px);
110110
`;
111111

112112
const videoPillStyles = css`

dotcom-rendering/src/types/mainMedia.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ type Media = {
88
};
99

1010
/** For displaying embedded, playable videos directly in cards */
11-
type YoutubeVideo = Media & {
11+
export type YoutubeVideo = Media & {
1212
type: 'YoutubeVideo';
1313
/** @see https://github.com/guardian/frontend/blob/8e7e4d0e/common/app/model/content/Atom.scala#L159 */
1414
id: string;

0 commit comments

Comments
 (0)