Skip to content

Commit b81048e

Browse files
abeddow91domlander
andauthored
Immersive feature splash (#13535)
* Add aspect ratio to card picture image widths * Add feature immersive as an image size type * Add feature immersive to card picture image width * Pass aspect ratio into picture image widths * remove aspect ratio from picture compontent as its not used * rearrange aspect ratio on youtube atom picture to be included in imagewidths * Add option for a mobile aspect ratio * add isImmersive prop to feature card * Add mobile aspect ratio prop * Render a feature card when immersive in flex gen splash * amend aspect ratios for immersive feature * Add missing mobile aspect ratio * Update comment * Add collection id to tests * comment out isImmersive prop whilst its not being used * remove isimmersive render prop * Use type imports and remove unused props * revert testing * Add immersive feature * Update dotcom-rendering/src/components/FlexibleGeneral.tsx Co-authored-by: Dominik Lander <[email protected]> --------- Co-authored-by: Dominik Lander <[email protected]>
1 parent c89db03 commit b81048e

File tree

9 files changed

+349
-98
lines changed

9 files changed

+349
-98
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export type ImageSizeType =
2626
| 'carousel'
2727
| 'podcast'
2828
| 'feature'
29-
| 'feature-large';
29+
| 'feature-large'
30+
| 'feature-immersive';
3031

3132
type Props = {
3233
children: React.ReactNode;

dotcom-rendering/src/components/CardPicture.tsx

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { css } from '@emotion/react';
2-
import { breakpoints, space } from '@guardian/source/foundations';
2+
import { breakpoints, space, until } from '@guardian/source/foundations';
33
import type { ImgHTMLAttributes } from 'react';
44
import React from 'react';
55
import type { AspectRatio } from '../types/front';
@@ -17,6 +17,7 @@ type Props = {
1717
roundedCorners?: boolean;
1818
isCircular?: boolean;
1919
aspectRatio?: AspectRatio;
20+
mobileAspectRatio?: AspectRatio;
2021
};
2122

2223
/**
@@ -29,6 +30,7 @@ type Props = {
2930
*/
3031
const decideImageWidths = (
3132
imageSize: ImageSizeType,
33+
aspectRatio: AspectRatio,
3234
): [ImageWidthType, ...ImageWidthType[]] => {
3335
switch (imageSize) {
3436
// @TODO missing image size option
@@ -40,52 +42,80 @@ const decideImageWidths = (
4042
// ];
4143

4244
case 'podcast':
43-
return [{ breakpoint: breakpoints.mobile, width: 80 }];
45+
return [{ breakpoint: breakpoints.mobile, width: 80, aspectRatio }];
4446

4547
case 'carousel':
46-
return [{ breakpoint: breakpoints.mobile, width: 220 }];
48+
return [
49+
{ breakpoint: breakpoints.mobile, width: 220, aspectRatio },
50+
];
4751

4852
case 'small':
4953
return [
50-
{ breakpoint: breakpoints.mobile, width: 120 },
51-
{ breakpoint: breakpoints.tablet, width: 160 },
52-
{ breakpoint: breakpoints.desktop, width: 220 },
54+
{ breakpoint: breakpoints.mobile, width: 120, aspectRatio },
55+
{ breakpoint: breakpoints.tablet, width: 160, aspectRatio },
56+
{ breakpoint: breakpoints.desktop, width: 220, aspectRatio },
5357
];
5458

5559
case 'medium':
5660
return [
57-
{ breakpoint: breakpoints.mobile, width: 240 },
58-
{ breakpoint: breakpoints.tablet, width: 330 },
59-
{ breakpoint: breakpoints.desktop, width: 460 },
61+
{ breakpoint: breakpoints.mobile, width: 240, aspectRatio },
62+
{ breakpoint: breakpoints.tablet, width: 330, aspectRatio },
63+
{ breakpoint: breakpoints.desktop, width: 460, aspectRatio },
6064
];
6165

6266
case 'large':
6367
return [
64-
{ breakpoint: breakpoints.mobile, width: 360 },
65-
{ breakpoint: breakpoints.mobileLandscape, width: 480 },
66-
{ breakpoint: breakpoints.tablet, width: 500 },
67-
{ breakpoint: breakpoints.desktop, width: 700 },
68+
{ breakpoint: breakpoints.mobile, width: 360, aspectRatio },
69+
{
70+
breakpoint: breakpoints.mobileLandscape,
71+
width: 480,
72+
aspectRatio,
73+
},
74+
{ breakpoint: breakpoints.tablet, width: 500, aspectRatio },
75+
{ breakpoint: breakpoints.desktop, width: 700, aspectRatio },
6876
];
6977

7078
case 'jumbo':
7179
return [
72-
{ breakpoint: breakpoints.mobile, width: 360 },
73-
{ breakpoint: breakpoints.mobileLandscape, width: 480 },
74-
{ breakpoint: breakpoints.tablet, width: 680 },
75-
{ breakpoint: breakpoints.desktop, width: 940 },
80+
{ breakpoint: breakpoints.mobile, width: 360, aspectRatio },
81+
{
82+
breakpoint: breakpoints.mobileLandscape,
83+
width: 480,
84+
aspectRatio,
85+
},
86+
{ breakpoint: breakpoints.tablet, width: 680, aspectRatio },
87+
{ breakpoint: breakpoints.desktop, width: 940, aspectRatio },
7688
];
7789

7890
case 'feature':
7991
return [
80-
{ breakpoint: breakpoints.mobile, width: 325 },
81-
{ breakpoint: breakpoints.tablet, width: 220 },
82-
{ breakpoint: breakpoints.desktop, width: 300 },
92+
{ breakpoint: breakpoints.mobile, width: 325, aspectRatio },
93+
{ breakpoint: breakpoints.tablet, width: 220, aspectRatio },
94+
{ breakpoint: breakpoints.desktop, width: 300, aspectRatio },
8395
];
8496
case 'feature-large':
8597
return [
86-
{ breakpoint: breakpoints.mobile, width: 325 },
87-
{ breakpoint: breakpoints.tablet, width: 337 },
88-
{ breakpoint: breakpoints.desktop, width: 460 },
98+
{ breakpoint: breakpoints.mobile, width: 325, aspectRatio },
99+
{ breakpoint: breakpoints.tablet, width: 337, aspectRatio },
100+
{ breakpoint: breakpoints.desktop, width: 460, aspectRatio },
101+
];
102+
case 'feature-immersive':
103+
return [
104+
{
105+
breakpoint: breakpoints.mobile,
106+
width: 340,
107+
aspectRatio: '4:5',
108+
},
109+
{
110+
breakpoint: breakpoints.tablet,
111+
width: 700,
112+
aspectRatio: '5:3',
113+
},
114+
{
115+
breakpoint: breakpoints.desktop,
116+
width: 940,
117+
aspectRatio: '5:3',
118+
},
89119
];
90120
}
91121
};
@@ -147,19 +177,28 @@ const circularStyles = css`
147177
width: 100%;
148178
`;
149179

180+
const decideMobileAspectRatioStyles = (aspectRatio?: AspectRatio) => {
181+
const paddingRatio = getAspectRatioPadding(aspectRatio);
182+
return css`
183+
${until.tablet} {
184+
padding-top: ${paddingRatio};
185+
}
186+
`;
187+
};
188+
150189
export const CardPicture = ({
151190
mainImage,
152191
alt,
153192
imageSize,
154193
loading,
155194
roundedCorners,
156195
isCircular,
157-
aspectRatio,
196+
aspectRatio = '5:3',
197+
mobileAspectRatio,
158198
}: Props) => {
159199
const sources = generateSources(
160200
mainImage,
161-
decideImageWidths(imageSize),
162-
aspectRatio,
201+
decideImageWidths(imageSize, aspectRatio),
163202
);
164203

165204
const fallbackSource = getFallbackSource(sources);
@@ -170,6 +209,8 @@ export const CardPicture = ({
170209
css={[
171210
block,
172211
decideAspectRatioStyles(aspectRatio),
212+
mobileAspectRatio &&
213+
decideMobileAspectRatioStyles(mobileAspectRatio),
173214
roundedCorners && borderRadius,
174215
isCircular && circularStyles,
175216
]}

dotcom-rendering/src/components/DecideContainer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ export const DecideContainer = ({
267267
imageLoading={imageLoading}
268268
aspectRatio={aspectRatio}
269269
containerLevel={containerLevel}
270+
collectionId={collectionId}
270271
/>
271272
);
272273
case 'scrollable/small':

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

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,17 @@ const aBasicLink = {
4444
},
4545
};
4646

47-
const CardWrapper = ({ children }: { children: React.ReactNode }) => {
47+
const CardWrapper = ({
48+
maxWidth,
49+
children,
50+
}: {
51+
maxWidth: string;
52+
children: React.ReactNode;
53+
}) => {
4854
return (
4955
<div
5056
css={css`
51-
max-width: 460px;
57+
max-width: ${maxWidth}px;
5258
flex-basis: 100%;
5359
${from.tablet} {
5460
flex-basis: 1;
@@ -61,16 +67,20 @@ const CardWrapper = ({ children }: { children: React.ReactNode }) => {
6167
);
6268
};
6369

70+
type FeatureCardArgsAndCustomArgs = React.ComponentProps<typeof FeatureCard> & {
71+
maxWidth: string;
72+
};
73+
6474
const meta = {
6575
component: FeatureCard,
6676
title: 'Components/FeatureCard',
67-
args: cardProps,
68-
render: (args) => (
69-
<CardWrapper>
77+
args: { ...cardProps, maxWidth: '460' },
78+
render: ({ maxWidth, ...args }) => (
79+
<CardWrapper maxWidth={maxWidth}>
7080
<FeatureCard {...args} />
7181
</CardWrapper>
7282
),
73-
} satisfies Meta<typeof FeatureCard>;
83+
} satisfies Meta<FeatureCardArgsAndCustomArgs>;
7484

7585
export default meta;
7686

@@ -244,3 +254,12 @@ export const WithSublinks: Story = {
244254
],
245255
},
246256
};
257+
258+
export const StandardImmersive: Story = {
259+
args: {
260+
aspectRatio: '5:3',
261+
mobileAspectRatio: '4:5',
262+
imageSize: 'feature-immersive',
263+
maxWidth: '940',
264+
},
265+
};

dotcom-rendering/src/components/FeatureCard.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,10 @@ export type Props = {
231231
discussionApiUrl: string;
232232
discussionId?: string;
233233
isExternalLink: boolean;
234-
/** Alows the consumer to set an aspect ratio on the image of 5:3 or 5:4 */
234+
/** Alows the consumer to set an aspect ratio on the image */
235235
aspectRatio?: AspectRatio;
236+
/** Alows the consumer to set an aspect ratio on the image specifically on mobile breakpoints */
237+
mobileAspectRatio?: AspectRatio;
236238
showQuotes?: boolean;
237239
/**
238240
* Youtube video requires a unique ID. We append the collectionId to the youtube asset ID, to allow
@@ -241,6 +243,11 @@ export type Props = {
241243
*/
242244
collectionId: number;
243245
isNewsletter?: boolean;
246+
/**
247+
* An immersive feature card variant. It dictates that the card has a full width background image on all breakpoints. It also dictates the the card change aspect ratio to 5:3 on desktop and 4:5 on mobile.
248+
*
249+
*/
250+
// isImmersive?: boolean;
244251
};
245252

246253
export const FeatureCard = ({
@@ -272,10 +279,11 @@ export const FeatureCard = ({
272279
isExternalLink,
273280
absoluteServerTimes,
274281
aspectRatio,
282+
mobileAspectRatio,
275283
starRating,
276284
showQuotes,
277285
collectionId,
278-
isNewsletter = false,
286+
isNewsletter = false, // isImmersive = false,
279287
}: Props) => {
280288
const hasSublinks = supportingContent && supportingContent.length > 0;
281289

@@ -397,6 +405,9 @@ export const FeatureCard = ({
397405
loading={imageLoading}
398406
roundedCorners={false}
399407
aspectRatio={aspectRatio}
408+
mobileAspectRatio={
409+
mobileAspectRatio
410+
}
400411
/>
401412
</div>
402413
)}
@@ -410,6 +421,9 @@ export const FeatureCard = ({
410421
loading={imageLoading}
411422
roundedCorners={false}
412423
aspectRatio={aspectRatio}
424+
mobileAspectRatio={
425+
mobileAspectRatio
426+
}
413427
/>
414428
{isVideoMainMedia &&
415429
mainMedia.duration > 0 && (

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ const meta = {
146146
absoluteServerTimes: true,
147147
imageLoading: 'eager',
148148
aspectRatio: '5:4',
149+
collectionId: 1,
149150
},
150151
render: ({ frontSectionTitle, ...args }) => (
151152
<FrontSection

0 commit comments

Comments
 (0)