Skip to content

Commit 64d4e24

Browse files
Merge pull request #13646 from bbc/WS-1891-portrait-video-carousel-articles
WS-1891: Portait Video Carousel on Articles
2 parents 895f104 + f43a18a commit 64d4e24

File tree

16 files changed

+286
-46
lines changed

16 files changed

+286
-46
lines changed

src/app/components/Curation/index.styles.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ const styles = {
88
position: 'relative',
99
zIndex: 1,
1010
}),
11+
12+
pvCarousel: ({ spacings, mq }: Theme) =>
13+
css({
14+
margin: `${spacings.DOUBLE}rem 0`,
15+
[mq.GROUP_1_MIN_WIDTH]: {
16+
margin: `${spacings.TRIPLE}rem 0`,
17+
},
18+
[mq.GROUP_3_MIN_WIDTH]: {
19+
margin: `${spacings.DOUBLE}rem 0`,
20+
},
21+
}),
1122
};
1223

1324
export default styles;

src/app/components/Curation/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ export default ({
173173
title={title}
174174
blocks={portraitVideo.blocks}
175175
eventTrackingData={eventTrackingData}
176+
css={styles.pvCarousel}
176177
/>
177178
);
178179
}

src/app/components/PortraitVideoCarousel/PortraitVideoCarouselNavigation/index.styles.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,26 @@ import { css, Theme } from '@emotion/react';
22
import pixelsToRem from '#app/utilities/pixelsToRem';
33
import { calculateVariedNavContainerWidths } from '../utils/styleUtils';
44

5+
const defaultBackgroundColor = 'rgba(255, 255, 255, 0.75)';
6+
57
const styles = {
6-
buttonGroupOverlay: ({ mq }: Theme) =>
7-
css({
8-
display: 'none',
9-
position: 'absolute',
10-
top: 0,
11-
insetInlineEnd: 0,
12-
height: '100%',
13-
backgroundColor: 'rgba(255, 255, 255, 0.75)',
14-
zIndex: 1,
15-
...calculateVariedNavContainerWidths({ mq, display: 'flex' }),
16-
}),
8+
buttonGroupOverlay:
9+
(backgroundColor = defaultBackgroundColor) =>
10+
({ mq, gridWidths }: Theme) =>
11+
css({
12+
display: 'none',
13+
position: 'absolute',
14+
top: 0,
15+
insetInlineEnd: 0,
16+
height: '100%',
17+
backgroundColor,
18+
zIndex: 1,
19+
...calculateVariedNavContainerWidths({
20+
mq,
21+
display: 'flex',
22+
gridWidths,
23+
}),
24+
}),
1725
buttonGroup: ({ spacings }: Theme) =>
1826
css({
1927
width: '100%',

src/app/components/PortraitVideoCarousel/PortraitVideoCarouselNavigation/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ type ScrollDirection = 'left' | 'right';
1313

1414
type PortraitVideoCarouselNavigationProps = {
1515
scrollPaneRef: RefObject<HTMLUListElement | null>;
16+
backgroundColor?: string;
1617
};
1718

18-
export default ({ scrollPaneRef }: PortraitVideoCarouselNavigationProps) => {
19+
export default ({
20+
scrollPaneRef,
21+
backgroundColor,
22+
}: PortraitVideoCarouselNavigationProps) => {
1923
const {
2024
dir,
2125
translations: { carousel = DEFAULT_TRANSLATION },
@@ -59,7 +63,7 @@ export default ({ scrollPaneRef }: PortraitVideoCarouselNavigationProps) => {
5963
}, [checkScrollButtons, scrollPaneRef]);
6064

6165
return (
62-
<div css={styles.buttonGroupOverlay} aria-hidden="true">
66+
<div css={styles.buttonGroupOverlay(backgroundColor)} aria-hidden="true">
6367
<div css={styles.buttonGroup}>
6468
<button
6569
type="button"

src/app/components/PortraitVideoCarousel/PortraitVideoPromo/index.styles.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import {
44
twoPixelFocusIndicatorThickness,
55
twoPixelFocusIndicatorStyle,
66
} from '#app/components/ThemeProvider/focusIndicator';
7-
import { calculatePromoWidth, PROMO_ITEM_WIDTH_MIN } from '../utils/styleUtils';
7+
import {
8+
calculatePromoWidth,
9+
PROMO_ITEM_WIDTH_MIN,
10+
getContainerQuery,
11+
} from '../utils/styleUtils';
812

913
const styles = {
10-
container: ({ mq, spacings }: Theme) =>
14+
container: ({ mq, spacings, gridWidths }: Theme) =>
1115
css({
1216
all: 'unset',
1317
scrollSnapAlign: 'start',
@@ -42,18 +46,22 @@ const styles = {
4246
},
4347
},
4448
[mq.GROUP_4_MIN_WIDTH]: {
45-
flexBasis: calculatePromoWidth({
46-
fitForNItems: 4,
47-
gapWidth: spacings.DOUBLE,
48-
navButtonAffordance: true,
49-
}),
49+
[getContainerQuery(gridWidths[900])]: {
50+
flexBasis: calculatePromoWidth({
51+
fitForNItems: 4,
52+
gapWidth: spacings.DOUBLE,
53+
navButtonAffordance: true,
54+
}),
55+
},
5056
},
5157
[mq.GROUP_5_MIN_WIDTH]: {
52-
flexBasis: calculatePromoWidth({
53-
fitForNItems: 5,
54-
gapWidth: spacings.DOUBLE,
55-
navButtonAffordance: true,
56-
}),
58+
[getContainerQuery(gridWidths[1008])]: {
59+
flexBasis: calculatePromoWidth({
60+
fitForNItems: 5,
61+
gapWidth: spacings.DOUBLE,
62+
navButtonAffordance: true,
63+
}),
64+
},
5765
},
5866
}),
5967
button: ({ palette }: Theme) =>

src/app/components/PortraitVideoCarousel/fixture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PortraitClipMediaBlock } from '../MediaLoader/types';
22

3-
const portraitVideoFixture = {
3+
export const portraitVideoFixture = {
44
title: 'Portrait Video Carousel',
55
curationId: 'urn:bbc:tipo:list:65faa8a9-78d7-46ea-a159-9bc06c6146f5',
66
blocks: [

src/app/components/PortraitVideoCarousel/index.stories.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ export default {
2626
parameters: {
2727
docs: { readme },
2828
metadata,
29+
chromatic: {
30+
viewports: [
31+
600, // Group 3
32+
1008, // Group 4
33+
1280, // Group 5
34+
],
35+
},
2936
},
3037
};
3138

src/app/components/PortraitVideoCarousel/index.styles.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,8 @@ import { OPERA_MINI_CLASSNAME } from '#app/lib/utilities/addOperaMiniClassScript
44
import { calculateVariedNavContainerWidths } from './utils/styleUtils';
55

66
const styles = {
7-
section: ({ mq, spacings }: Theme) =>
7+
section: () =>
88
css({
9-
margin: `${spacings.DOUBLE}rem 0`,
10-
[mq.GROUP_1_MIN_WIDTH]: {
11-
margin: `${spacings.TRIPLE}rem 0`,
12-
},
13-
[mq.GROUP_3_MIN_WIDTH]: {
14-
margin: `${spacings.DOUBLE}rem 0`,
15-
},
169
[`.${OPERA_MINI_CLASSNAME} &`]: {
1710
display: 'none',
1811
},
@@ -31,12 +24,14 @@ const styles = {
3124
position: 'relative',
3225
display: 'flex',
3326
alignItems: 'center',
27+
containerType: 'inline-size', // required for container query
3428
[`.${NO_JS_CLASSNAME} &`]: {
3529
display: 'none',
3630
},
3731
}),
38-
carousel: ({ spacings, mq }: Theme) =>
32+
carousel: ({ spacings, mq, gridWidths }: Theme) =>
3933
css({
34+
containerType: 'inline-size', // required for container query
4035
display: 'flex',
4136
flex: 1,
4237
overflowX: 'auto',
@@ -61,6 +56,7 @@ const styles = {
6156
mq,
6257
display: 'block',
6358
widthParameter: 'flexBasis',
59+
gridWidths,
6460
}),
6561
},
6662
}),

src/app/components/PortraitVideoCarousel/index.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ type PortraitVideoCarouselProps = {
1919
title: string;
2020
blocks: PortraitClipMediaBlock[];
2121
eventTrackingData: EventTrackingData;
22+
className?: string;
23+
backgroundColor?: string;
2224
};
2325

2426
const PortraitVideoCarousel = ({
2527
title,
2628
blocks,
2729
eventTrackingData,
30+
className,
31+
backgroundColor,
2832
}: PortraitVideoCarouselProps) => {
2933
const scrollRef = useRef<HTMLUListElement>(null);
3034
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -79,6 +83,7 @@ const PortraitVideoCarousel = ({
7983
role="region"
8084
data-testid="portrait-video-carousel"
8185
css={styles.section}
86+
className={className}
8287
{...viewTracker}
8388
>
8489
<Heading
@@ -93,7 +98,10 @@ const PortraitVideoCarousel = ({
9398
<PortraitVideoNoJs />
9499
</noscript>
95100
<div css={styles.carouselContainer}>
96-
<PortraitCarouselNavigation scrollPaneRef={scrollRef} />
101+
<PortraitCarouselNavigation
102+
scrollPaneRef={scrollRef}
103+
backgroundColor={backgroundColor}
104+
/>
97105
<ul
98106
ref={scrollRef}
99107
css={styles.carousel}

src/app/components/PortraitVideoCarousel/utils/styleUtils.test.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Theme } from '@emotion/react';
2-
2+
import pixelsToRem from '#app/utilities/pixelsToRem';
33
import {
44
calculatePromoWidth,
55
calculateVariedNavContainerWidths,
@@ -41,11 +41,26 @@ describe('styleUtils', () => {
4141
POINTER: 'pointer',
4242
} as Theme['mq'];
4343

44+
const mockGridWidths = {
45+
900: 900,
46+
1008: 1008,
47+
} as Theme['gridWidths'];
48+
4449
const navButtonWidths = calculateVariedNavContainerWidths({
4550
mq: mockMq,
4651
display: 'block',
4752
widthParameter: 'flexBasis',
53+
gridWidths: mockGridWidths,
4854
});
55+
56+
const expectedContainerQueryGroup4 = `@container (min-width: ${pixelsToRem(
57+
900,
58+
)}rem)`;
59+
60+
const expectedContainerQueryGroup5 = `@container (min-width: ${pixelsToRem(
61+
1008,
62+
)}rem)`;
63+
4964
expect(navButtonWidths).toStrictEqual({
5065
'group 3 min': {
5166
pointer: {
@@ -54,12 +69,16 @@ describe('styleUtils', () => {
5469
},
5570
},
5671
'group 4 min': {
57-
display: 'block',
58-
flexBasis: 'calc(calc((100% / 4.5) - 0rem) * 0.5)',
72+
[expectedContainerQueryGroup4]: {
73+
display: 'block',
74+
flexBasis: 'calc(calc((100% / 4.5) - 0rem) * 0.5)',
75+
},
5976
},
6077
'group 5 min': {
61-
display: 'block',
62-
flexBasis: 'calc(calc((100% / 5.5) - 0rem) * 0.5)',
78+
[expectedContainerQueryGroup5]: {
79+
display: 'block',
80+
flexBasis: 'calc(calc((100% / 5.5) - 0rem) * 0.5)',
81+
},
6382
},
6483
});
6584
});

0 commit comments

Comments
 (0)