Skip to content

Commit 0366c04

Browse files
committed
Use subtitles file and use in looping video
1 parent 095e662 commit 0366c04

File tree

12 files changed

+103
-8
lines changed

12 files changed

+103
-8
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { CardPicture } from '../CardPicture';
4242
import { Island } from '../Island';
4343
import { LatestLinks } from '../LatestLinks.importable';
4444
import { LoopVideo } from '../LoopVideo.importable';
45+
import type { SubtitleSize } from '../LoopVideoPlayer';
4546
import { Pill } from '../Pill';
4647
import { SlideshowCarousel } from '../SlideshowCarousel.importable';
4748
import { Snap } from '../Snap';
@@ -159,6 +160,7 @@ export type Props = {
159160
showKickerImage?: boolean;
160161
isInAllBoostsTest?: boolean;
161162
fixImageWidth?: boolean;
163+
subtitleSize?: SubtitleSize;
162164
/** Determines if the headline should be positioned within the content or outside the content */
163165
headlinePosition?: 'inner' | 'outer';
164166
/** Feature flag for the labs redesign work */
@@ -404,6 +406,7 @@ export const Card = ({
404406
isInAllBoostsTest = false,
405407
headlinePosition = 'inner',
406408
showLabsRedesign = false,
409+
subtitleSize = 'small',
407410
}: Props) => {
408411
const hasSublinks = supportingContent && supportingContent.length > 0;
409412
const sublinkPosition = decideSublinkPosition(
@@ -969,6 +972,10 @@ export const Card = ({
969972
fallbackImageAlt={media.imageAltText}
970973
fallbackImageAspectRatio="5:4"
971974
linkTo={linkTo}
975+
subtitleSource={
976+
media.mainMedia.subtitleSource
977+
}
978+
subtitleSize={subtitleSize}
972979
/>
973980
</Island>
974981
)}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ export const SplashBoostLevels: Story = {
324324

325325
return (
326326
<>
327+
<Section title="Default" boostLevel="default" />
327328
<Section title="Boosted" boostLevel="boost" />
328329
<Section title="Mega boosted" boostLevel="megaboost" />
329330
<Section title="Giga boosted" boostLevel="gigaboost" />

dotcom-rendering/src/components/FlexibleGeneral.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type { ResponsiveFontSize } from './CardHeadline';
2121
import type { Loading } from './CardPicture';
2222
import { FeatureCard } from './FeatureCard';
2323
import { FrontCard } from './FrontCard';
24+
import type { SubtitleSize } from './LoopVideoPlayer';
2425
import type { Alignment } from './SupportingContent';
2526

2627
type Props = {
@@ -153,6 +154,7 @@ type BoostedSplashProperties = {
153154
supportingContentAlignment: Alignment;
154155
liveUpdatesAlignment: Alignment;
155156
trailTextSize: TrailTextSize;
157+
subtitleSize: SubtitleSize;
156158
avatarUrl?: string;
157159
};
158160

@@ -183,6 +185,7 @@ const decideSplashCardProperties = (
183185
supportingContentLength >= 4 ? 'horizontal' : 'vertical',
184186
liveUpdatesAlignment: 'vertical',
185187
trailTextSize: 'regular',
188+
subtitleSize: 'medium',
186189
};
187190
case 'boost':
188191
return {
@@ -198,6 +201,7 @@ const decideSplashCardProperties = (
198201
supportingContentLength >= 4 ? 'horizontal' : 'vertical',
199202
liveUpdatesAlignment: 'vertical',
200203
trailTextSize: 'regular',
204+
subtitleSize: 'medium',
201205
};
202206
case 'megaboost':
203207
return {
@@ -214,6 +218,7 @@ const decideSplashCardProperties = (
214218
supportingContentAlignment: 'horizontal',
215219
liveUpdatesAlignment: 'horizontal',
216220
trailTextSize: 'large',
221+
subtitleSize: 'large',
217222
};
218223
case 'gigaboost':
219224
return {
@@ -230,6 +235,7 @@ const decideSplashCardProperties = (
230235
supportingContentAlignment: 'horizontal',
231236
liveUpdatesAlignment: 'horizontal',
232237
trailTextSize: 'large',
238+
subtitleSize: 'large',
233239
};
234240
}
235241
};
@@ -290,6 +296,7 @@ const SplashCardLayout = ({
290296
supportingContentAlignment,
291297
liveUpdatesAlignment,
292298
trailTextSize,
299+
subtitleSize,
293300
} = decideSplashCardProperties(
294301
card.boostLevel ?? 'default',
295302
card.supportingContent?.length ?? 0,
@@ -339,6 +346,7 @@ const SplashCardLayout = ({
339346
trailTextSize={trailTextSize}
340347
canPlayInline={true}
341348
showKickerImage={card.format.design === ArticleDesign.Audio}
349+
subtitleSize={subtitleSize}
342350
headlinePosition={card.showLivePlayable ? 'outer' : 'inner'}
343351
showLabsRedesign={showLabsRedesign}
344352
/>
@@ -352,6 +360,7 @@ type BoostedCardProperties = {
352360
mediaSize: MediaSizeType;
353361
liveUpdatesPosition: Position;
354362
supportingContentAlignment: Alignment;
363+
subtitleSize: SubtitleSize;
355364
};
356365

357366
/**
@@ -375,6 +384,7 @@ const decideCardProperties = (
375384
liveUpdatesPosition: 'outer',
376385
supportingContentAlignment:
377386
supportingContentLength >= 2 ? 'horizontal' : 'vertical',
387+
subtitleSize: 'medium',
378388
};
379389
case 'boost':
380390
default:
@@ -388,6 +398,7 @@ const decideCardProperties = (
388398
liveUpdatesPosition: 'inner',
389399
supportingContentAlignment:
390400
supportingContentLength >= 2 ? 'horizontal' : 'vertical',
401+
subtitleSize: 'small',
391402
};
392403
}
393404
};
@@ -428,6 +439,7 @@ const FullWidthCardLayout = ({
428439
mediaSize,
429440
supportingContentAlignment,
430441
liveUpdatesPosition,
442+
subtitleSize,
431443
} = decideCardProperties(
432444
card.supportingContent?.length ?? 0,
433445
card.boostLevel,
@@ -492,6 +504,7 @@ const FullWidthCardLayout = ({
492504
canPlayInline={true}
493505
showKickerImage={card.format.design === ArticleDesign.Audio}
494506
showLabsRedesign={showLabsRedesign}
507+
subtitleSize={subtitleSize}
495508
/>
496509
</LI>
497510
</UL>

dotcom-rendering/src/components/FlexibleSpecial.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { UL } from './Card/components/UL';
1919
import type { ResponsiveFontSize } from './CardHeadline';
2020
import type { Loading } from './CardPicture';
2121
import { FrontCard } from './FrontCard';
22+
import type { SubtitleSize } from './LoopVideoPlayer';
2223
import type { Alignment } from './SupportingContent';
2324

2425
type Props = {
@@ -42,6 +43,7 @@ type BoostProperties = {
4243
supportingContentAlignment: Alignment;
4344
liveUpdatesAlignment: Alignment;
4445
trailTextSize: TrailTextSize;
46+
subtitleSize: SubtitleSize;
4547
};
4648

4749
/**
@@ -70,6 +72,7 @@ const determineCardProperties = (
7072
supportingContentLength >= 3 ? 'horizontal' : 'vertical',
7173
liveUpdatesAlignment: 'vertical',
7274
trailTextSize: 'regular',
75+
subtitleSize: 'medium',
7376
};
7477
case 'boost':
7578
return {
@@ -85,6 +88,7 @@ const determineCardProperties = (
8588
supportingContentLength >= 3 ? 'horizontal' : 'vertical',
8689
liveUpdatesAlignment: 'vertical',
8790
trailTextSize: 'regular',
91+
subtitleSize: 'medium',
8892
};
8993
case 'megaboost':
9094
return {
@@ -99,6 +103,7 @@ const determineCardProperties = (
99103
supportingContentAlignment: 'horizontal',
100104
liveUpdatesAlignment: 'horizontal',
101105
trailTextSize: 'large',
106+
subtitleSize: 'large',
102107
};
103108
case 'gigaboost':
104109
return {
@@ -113,6 +118,7 @@ const determineCardProperties = (
113118
supportingContentAlignment: 'horizontal',
114119
liveUpdatesAlignment: 'horizontal',
115120
trailTextSize: 'large',
121+
subtitleSize: 'large',
116122
};
117123
}
118124
};
@@ -155,6 +161,7 @@ export const OneCardLayout = ({
155161
supportingContentAlignment,
156162
liveUpdatesAlignment,
157163
trailTextSize,
164+
subtitleSize,
158165
} = determineCardProperties(
159166
card.boostLevel ?? 'default',
160167
card.supportingContent?.length ?? 0,
@@ -195,6 +202,7 @@ export const OneCardLayout = ({
195202
showKickerImage={card.format.design === ArticleDesign.Audio}
196203
headlinePosition={isSplashCard ? 'outer' : 'inner'}
197204
showLabsRedesign={showLabsRedesign}
205+
subtitleSize={subtitleSize}
198206
/>
199207
</LI>
200208
</UL>

dotcom-rendering/src/components/LoopVideo.importable.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ import {
1818
} from '../lib/video';
1919
import { CardPicture, type Props as CardPictureProps } from './CardPicture';
2020
import { useConfig } from './ConfigContext';
21+
import type {
22+
PLAYER_STATES,
23+
PlayerStates,
24+
SubtitleSize,
25+
} from './LoopVideoPlayer';
2126
import { LoopVideoPlayer } from './LoopVideoPlayer';
22-
import type { PLAYER_STATES, PlayerStates } from './LoopVideoPlayer';
2327
import { ophanTrackerWeb } from './YoutubeAtom/eventEmitters';
2428

2529
const videoContainerStyles = css`
@@ -117,6 +121,8 @@ type Props = {
117121
fallbackImageAlt: CardPictureProps['alt'];
118122
fallbackImageAspectRatio: CardPictureProps['aspectRatio'];
119123
linkTo: string;
124+
subtitleSource?: string;
125+
subtitleSize: SubtitleSize;
120126
};
121127

122128
export const LoopVideo = ({
@@ -132,6 +138,8 @@ export const LoopVideo = ({
132138
fallbackImageAlt,
133139
fallbackImageAspectRatio,
134140
linkTo,
141+
subtitleSource,
142+
subtitleSize,
135143
}: Props) => {
136144
const adapted = useShouldAdapt();
137145
const { renderingTarget } = useConfig();
@@ -627,6 +635,8 @@ export const LoopVideo = ({
627635
AudioIcon={hasAudio ? AudioIcon : null}
628636
preloadPartialData={preloadPartialData}
629637
showPlayIcon={showPlayIcon}
638+
subtitleSource={subtitleSource}
639+
subtitleSize={subtitleSize}
630640
/>
631641
</figure>
632642
);

dotcom-rendering/src/components/LoopVideoPlayer.tsx

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { css } from '@emotion/react';
2-
import { space } from '@guardian/source/foundations';
2+
import {
3+
space,
4+
textSans15,
5+
textSans17,
6+
textSans20,
7+
} from '@guardian/source/foundations';
38
import type { IconProps } from '@guardian/source/react-components';
49
import type {
510
Dispatch,
@@ -13,7 +18,13 @@ import { palette } from '../palette';
1318
import { narrowPlayIconWidth, PlayIcon } from './Card/components/PlayIcon';
1419
import { LoopVideoProgressBar } from './LoopVideoProgressBar';
1520

16-
const videoStyles = (width: number, height: number) => css`
21+
export type SubtitleSize = 'small' | 'medium' | 'large';
22+
23+
const videoStyles = (
24+
width: number,
25+
height: number,
26+
subtitleSize: SubtitleSize,
27+
) => css`
1728
position: relative;
1829
display: block;
1930
height: auto;
@@ -22,6 +33,15 @@ const videoStyles = (width: number, height: number) => css`
2233
/* Prevents CLS by letting the browser know the space the video will take up. */
2334
aspect-ratio: ${width} / ${height};
2435
object-fit: cover;
36+
37+
::cue {
38+
background-color: ${palette('--loop-video-subtitle-background')};
39+
color: ${palette('--loop-video-subtitle-text')};
40+
41+
${subtitleSize === 'small' && textSans15};
42+
${subtitleSize === 'medium' && textSans17};
43+
${subtitleSize === 'large' && textSans20};
44+
}
2545
`;
2646

2747
const playIconStyles = css`
@@ -97,6 +117,8 @@ type Props = {
97117
posterImage?: string;
98118
preloadPartialData: boolean;
99119
showPlayIcon: boolean;
120+
subtitleSource?: string;
121+
subtitleSize: SubtitleSize;
100122
};
101123

102124
/**
@@ -128,6 +150,8 @@ export const LoopVideoPlayer = forwardRef(
128150
AudioIcon,
129151
preloadPartialData,
130152
showPlayIcon,
153+
subtitleSource,
154+
subtitleSize,
131155
}: Props,
132156
ref: React.ForwardedRef<HTMLVideoElement>,
133157
) => {
@@ -138,7 +162,7 @@ export const LoopVideoPlayer = forwardRef(
138162
{/* eslint-disable-next-line jsx-a11y/media-has-caption -- Captions will be considered later. */}
139163
<video
140164
id={loopVideoId}
141-
css={videoStyles(width, height)}
165+
css={videoStyles(width, height, subtitleSize)}
142166
ref={ref}
143167
tabIndex={0}
144168
data-testid="loop-video"
@@ -179,6 +203,13 @@ export const LoopVideoPlayer = forwardRef(
179203
type={source.mimeType}
180204
/>
181205
))}
206+
{subtitleSource !== undefined && (
207+
<track
208+
default={true}
209+
kind="subtitles"
210+
src={subtitleSource}
211+
/>
212+
)}
182213
{FallbackImageComponent}
183214
</video>
184215
{ref && 'current' in ref && ref.current && isPlayable && (

dotcom-rendering/src/frontend/schemas/feArticle.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5315,6 +5315,9 @@
53155315
"duration": {
53165316
"type": "number"
53175317
},
5318+
"subtitleSource": {
5319+
"type": "string"
5320+
},
53185321
"image": {
53195322
"type": "string"
53205323
}

dotcom-rendering/src/frontend/schemas/feFront.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,6 +3953,9 @@
39533953
"duration": {
39543954
"type": "number"
39553955
},
3956+
"subtitleSource": {
3957+
"type": "string"
3958+
},
39563959
"image": {
39573960
"type": "string"
39583961
}

dotcom-rendering/src/model/enhanceCards.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ describe('Enhance Cards', () => {
100100
duration: 15,
101101
height: 400,
102102
image: '',
103+
subtitleSource: 'https://guim-example.co.uk/atomID-1.vtt',
103104
type: 'LoopVideo',
104105
sources: [
105106
{

0 commit comments

Comments
 (0)