Skip to content

Commit 24eef8f

Browse files
arelraJamieB-gumarjisound
committed
MainMediaGallery renders picture sources
Co-authored-by: Jamie B <[email protected]> Co-authored-by: Marjan Kalanaki <[email protected]>
1 parent c96d54f commit 24eef8f

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { Meta, StoryObj } from '@storybook/react';
2+
import { images } from '../../fixtures/generated/images';
3+
import { grid } from '../grid';
4+
import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat';
25
import { MainMediaGallery } from './MainMediaGallery';
36

47
const meta = {
@@ -11,5 +14,20 @@ export default meta;
1114
type Story = StoryObj<typeof meta>;
1215

1316
export const FirstStory = {
14-
args: {},
17+
args: {
18+
mainMedia: images[0],
19+
format: {
20+
design: ArticleDesign.Gallery,
21+
display: ArticleDisplay.Standard,
22+
theme: Pillar.News,
23+
},
24+
},
25+
decorators: [
26+
// To make it easier to see the top border above the date
27+
(Story) => (
28+
<div css={[grid.container]}>
29+
<Story />
30+
</div>
31+
),
32+
],
1533
} satisfies Story;
Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,62 @@
1-
export const MainMediaGallery = () => <>Hello world</>;
1+
import { css } from '@emotion/react';
2+
import { breakpoints, from } from '@guardian/source/foundations';
3+
import { grid } from '../grid';
4+
import { type ArticleFormat } from '../lib/articleFormat';
5+
import { getImage } from '../lib/image';
6+
import { type ImageBlockElement } from '../types/content';
7+
import { generateSources, Sources } from './Picture';
8+
9+
type Props = {
10+
mainMedia: ImageBlockElement;
11+
format: ArticleFormat;
12+
};
13+
14+
const styles = css`
15+
${grid.column.all}
16+
height: calc(80vh - 48px);
17+
grid-row: 1/5;
18+
${from.desktop} {
19+
height: calc(100vh - 48px);
20+
}
21+
`;
22+
23+
export const MainMediaGallery = ({ mainMedia, format }: Props) => {
24+
const asset = getImage(mainMedia.media.allImages);
25+
26+
if (asset === undefined) {
27+
return null;
28+
}
29+
30+
const width = parseInt(asset.fields.width, 10);
31+
const height = parseInt(asset.fields.height, 10);
32+
33+
if (isNaN(width) || isNaN(height)) {
34+
return null;
35+
}
36+
37+
const sources = generateSources(asset.url, [
38+
{ breakpoint: breakpoints.mobile, width: 480 },
39+
{ breakpoint: breakpoints.mobileLandscape, width: 660 },
40+
{ breakpoint: breakpoints.phablet, width: 740 },
41+
{ breakpoint: breakpoints.tablet, width: 980 },
42+
{ breakpoint: breakpoints.desktop, width: 1140 },
43+
{ breakpoint: breakpoints.leftCol, width: 1300 },
44+
{ breakpoint: breakpoints.wide, width: 1900 },
45+
] as const);
46+
47+
const fallbackSource = sources[0];
48+
49+
return (
50+
<figure css={styles}>
51+
<picture>
52+
<Sources sources={sources} />
53+
<img
54+
alt={mainMedia.data.alt}
55+
src={fallbackSource?.lowResUrl}
56+
width={fallbackSource?.width}
57+
height={(fallbackSource?.width ?? 1) * 1.0}
58+
/>
59+
</picture>
60+
</figure>
61+
);
62+
};

dotcom-rendering/src/lib/image.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,20 @@ export const generateImageURL = ({
7878
url.pathname
7979
}?${params.toString()}`;
8080
};
81+
82+
export const isSupported = (imageUrl: string): boolean => {
83+
const supportedImages = ['jpg', 'jpeg', 'png', 'gif'];
84+
return supportedImages.some((extension) =>
85+
imageUrl.endsWith(`.${extension}`),
86+
);
87+
};
88+
89+
export const getImage = (images: Image[]): Image | undefined => {
90+
const image = getMaster(images) ?? getLargest(images);
91+
92+
if (image?.url === undefined || !isSupported(image.url)) {
93+
return undefined;
94+
}
95+
96+
return image;
97+
};

0 commit comments

Comments
 (0)