Skip to content

Commit 7424d2b

Browse files
committed
Add ScrollableSmallOnwards components
1 parent 9d9cb06 commit 7424d2b

File tree

9 files changed

+480
-73
lines changed

9 files changed

+480
-73
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,8 @@ export const Card = ({
547547
- */
548548
const isMediaCardOrNewsletter = isMediaCard(format) || isNewsletter;
549549

550-
const showPill = isMediaCardOrNewsletter;
550+
const isOnwardRelatedContent = onwardsSource === 'related-content'; // TODO
551+
const showPill = isMediaCardOrNewsletter && !isOnwardRelatedContent;
551552

552553
const media = getMedia({
553554
imageUrl: image?.src,

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

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { RenderingTarget } from '../types/renderingTarget';
1414
import type { FETrailType, TrailType } from '../types/trails';
1515
import { Carousel } from './Carousel.importable';
1616
import { Placeholder } from './Placeholder';
17+
import { ScrollableSmallOnwards } from './ScrollableSmallOnwards';
1718

1819
type Props = {
1920
url: string;
@@ -121,22 +122,32 @@ export const FetchOnwardsData = ({
121122

122123
return (
123124
<div ref={setIsInViewRef} css={minHeight}>
124-
<Carousel
125-
heading={data.heading || data.displayname} // Sometimes the api returns heading as 'displayName'
126-
trails={trails}
127-
description={data.description}
128-
onwardsSource={onwardsSource}
129-
format={format}
130-
leftColSize={
131-
format.design === ArticleDesign.LiveBlog ||
132-
format.design === ArticleDesign.DeadBlog
133-
? 'wide'
134-
: 'compact'
135-
}
136-
discussionApiUrl={discussionApiUrl}
137-
serverTime={serverTime}
138-
renderingTarget={renderingTarget}
139-
/>
125+
{format.design === ArticleDesign.Gallery ? (
126+
<ScrollableSmallOnwards
127+
serverTime={serverTime}
128+
trails={trails}
129+
discussionApiUrl={discussionApiUrl}
130+
heading={data.heading || data.displayname}
131+
onwardsSource={onwardsSource}
132+
/>
133+
) : (
134+
<Carousel
135+
heading={data.heading || data.displayname} // Sometimes the api returns heading as 'displayName'
136+
trails={trails}
137+
description={data.description}
138+
onwardsSource={onwardsSource}
139+
format={format}
140+
leftColSize={
141+
format.design === ArticleDesign.LiveBlog ||
142+
format.design === ArticleDesign.DeadBlog
143+
? 'wide'
144+
: 'compact'
145+
}
146+
discussionApiUrl={discussionApiUrl}
147+
serverTime={serverTime}
148+
renderingTarget={renderingTarget}
149+
/>
150+
)}
140151
</div>
141152
);
142153
};

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,15 @@ export const OnwardsUpper = ({
321321
<Section
322322
fullWidth={true}
323323
borderColour={palette('--article-section-border')}
324+
padSides={
325+
format.design === ArticleDesign.Gallery ? false : true
326+
}
327+
showTopBorder={
328+
format.design === ArticleDesign.Gallery ? false : true
329+
}
330+
showSideBorders={
331+
format.design === ArticleDesign.Gallery ? false : true
332+
}
324333
>
325334
<FetchOnwardsData
326335
url={url}
@@ -340,6 +349,15 @@ export const OnwardsUpper = ({
340349
<Section
341350
fullWidth={true}
342351
borderColour={palette('--article-section-border')}
352+
showTopBorder={
353+
format.design === ArticleDesign.Gallery ? false : true
354+
}
355+
showSideBorders={
356+
format.design === ArticleDesign.Gallery ? false : true
357+
}
358+
padSides={
359+
format.design === ArticleDesign.Gallery ? false : true
360+
}
343361
>
344362
<FetchOnwardsData
345363
url={curatedDataUrl}

dotcom-rendering/src/components/ScrollableCarousel.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,32 +104,34 @@ const itemStyles = css`
104104
position: relative;
105105
`;
106106

107-
const leftBorderStyles = css`
107+
const leftBorderStyles = (isOnwardContent?: boolean) => css`
108108
content: '';
109109
position: absolute;
110110
top: 0;
111111
bottom: 0;
112112
left: -10px;
113113
width: 1px;
114-
background-color: ${palette('--card-border-top')};
114+
background-color: ${isOnwardContent
115+
? palette('--onward-content-border')
116+
: palette('--card-border-top')};
115117
transform: translateX(-50%);
116118
`;
117119

118-
const singleRowLeftBorderStyles = css`
120+
const singleRowLeftBorderStyles = (isOnwardContent?: boolean) => css`
119121
:not(:first-child)::before {
120-
${leftBorderStyles}
122+
${leftBorderStyles(isOnwardContent)}
121123
}
122124
`;
123125

124-
const stackedRowLeftBorderStyles = css`
126+
const stackedRowLeftBorderStyles = (isOnwardContent?: boolean) => css`
125127
${from.tablet} {
126128
:not(:first-child)::before {
127-
${leftBorderStyles}
129+
${leftBorderStyles(isOnwardContent)}
128130
}
129131
}
130132
${until.tablet} {
131133
:not(:first-child):not(:nth-child(2))::before {
132-
${leftBorderStyles}
134+
${leftBorderStyles(isOnwardContent)}
133135
}
134136
}
135137
`;
@@ -410,17 +412,20 @@ export const ScrollableCarousel = ({
410412

411413
ScrollableCarousel.Item = ({
412414
isStackingCarousel = false,
415+
isOnwardContent = false,
413416
children,
414417
}: {
415418
isStackingCarousel?: boolean;
419+
/** The colour of borders can be overriden */
420+
isOnwardContent?: boolean;
416421
children: React.ReactNode;
417422
}) => (
418423
<li
419424
css={[
420425
itemStyles,
421426
isStackingCarousel
422-
? stackedRowLeftBorderStyles
423-
: singleRowLeftBorderStyles,
427+
? stackedRowLeftBorderStyles(isOnwardContent)
428+
: singleRowLeftBorderStyles(isOnwardContent),
424429
]}
425430
>
426431
{children}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
2+
import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat';
3+
import { getDataLinkNameCard } from '../lib/getDataLinkName';
4+
import { ScrollableSmallOnwards } from './ScrollableSmallOnwards';
5+
6+
const meta = {
7+
title: 'Components/ScrollableSmallOnwards',
8+
component: ScrollableSmallOnwards,
9+
} satisfies Meta<typeof ScrollableSmallOnwards>;
10+
11+
export default meta;
12+
13+
type Story = StoryObj<typeof meta>;
14+
15+
export const ScrollableSmallOnwardsStory = {
16+
args: {
17+
serverTime: undefined, // TODO
18+
discussionApiUrl:
19+
'https://discussion.code.dev-theguardian.com/discussion-api',
20+
heading: 'More on this story',
21+
headingUrl: 'http://localhost:9000/more-galleries',
22+
onwardsSource: 'more-galleries',
23+
trails: [
24+
{
25+
url: 'http://localhost:9000/environment/gallery/2025/aug/22/week-in-wildlife-a-clumsy-fox-swinging-orangutang-and-rescued-jaguarundi-cub',
26+
linkText:
27+
'Week in wildlife: a clumsy fox, a swinging orangutan and a rescued jaguarundi cub',
28+
showByline: false,
29+
byline: 'Pejman Faratin',
30+
image: {
31+
src: 'https://media.guim.co.uk/a81e974ffee6c8c88fa280c2d02eaf5dc2af863e/151_292_1020_816/master/1020.jpg',
32+
altText: '',
33+
},
34+
format: {
35+
theme: Pillar.News,
36+
design: ArticleDesign.Gallery,
37+
display: ArticleDisplay.Standard,
38+
},
39+
webPublicationDate: '2022-01-01T06:00:25.000Z',
40+
headline:
41+
'Week in wildlife: a clumsy fox, a swinging orangutan and a rescued jaguarundi cub',
42+
shortUrl: 'https://www.theguardian.com/p/x32n89',
43+
discussion: {
44+
isCommentable: false,
45+
isClosedForComments: true,
46+
discussionId: '/p/x32n89',
47+
},
48+
discussionId: 'zHoBy6HNKsk',
49+
dataLinkName: getDataLinkNameCard(
50+
{
51+
theme: Pillar.News,
52+
design: ArticleDesign.Gallery,
53+
display: ArticleDisplay.Standard,
54+
},
55+
'0',
56+
0,
57+
),
58+
trailText:
59+
'Guinness World Records is looking back at the extraordinary feats achieved since its inception - as well as unveiling 70 whacky and unclaimed records ',
60+
kickerText: 'Politics', // Get data for this
61+
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
62+
},
63+
{
64+
url: 'http://localhost:9000/money/gallery/2025/aug/22/characterful-cottages-for-sale-in-england-in-pictures',
65+
linkText:
66+
'Characterful cottages for sale in England – in pictures',
67+
showByline: false,
68+
byline: 'Anna White',
69+
image: {
70+
src: 'https://media.guim.co.uk/58cd9356e6d68e8efa6028162bb959f9798307d5/515_0_5000_4000/master/5000.jpg',
71+
altText: '',
72+
},
73+
format: {
74+
design: ArticleDesign.Gallery,
75+
theme: Pillar.Lifestyle,
76+
display: ArticleDisplay.Standard,
77+
},
78+
webPublicationDate: '2022-01-01T06:00:24.000Z',
79+
headline:
80+
'Characterful cottages for sale in England – in pictures',
81+
shortUrl: 'https://www.theguardian.com/p/x32gqj',
82+
discussion: {
83+
isCommentable: false,
84+
isClosedForComments: true,
85+
discussionId: '/p/x32gqj',
86+
},
87+
dataLinkName: getDataLinkNameCard(
88+
{
89+
design: ArticleDesign.Gallery,
90+
theme: Pillar.Lifestyle,
91+
display: ArticleDisplay.Standard,
92+
},
93+
'0',
94+
1,
95+
),
96+
trailText:
97+
'Picked from a record 60,636 entries, the first images from the Natural History Museum’s wildlife photographer of the year competition have been released. The photographs, which range from a lion facing down a cobra to magnified mould spores, show the diversity, beauty and complexity of the natural world and humanity’s relationship with it',
98+
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
99+
},
100+
{
101+
url: 'http://localhost:9000/news/gallery/2025/aug/22/sunsets-aid-parachutes-and-giant-pandas-photos-of-the-day-friday',
102+
linkText:
103+
'Sunsets, aid parachutes and giant pandas: photos of the day – Friday ',
104+
showByline: false,
105+
byline: 'Eithne Staunton',
106+
image: {
107+
src: 'https://media.guim.co.uk/4ce0b080206fe9b65b976c1acf219d81072cc814/0_0_2113_1690/master/2113.png',
108+
altText: '',
109+
},
110+
format: {
111+
design: ArticleDesign.Gallery,
112+
theme: Pillar.News,
113+
display: ArticleDisplay.Standard,
114+
},
115+
webPublicationDate: '2022-01-01T08:49:42.000Z',
116+
headline:
117+
'Sunsets, aid parachutes and giant pandas: photos of the day – Friday ',
118+
shortUrl: 'https://www.theguardian.com/p/x3359z',
119+
discussion: {
120+
isCommentable: false,
121+
isClosedForComments: true,
122+
discussionId: '/p/x3359z',
123+
},
124+
dataLinkName: getDataLinkNameCard(
125+
{
126+
design: ArticleDesign.Gallery,
127+
theme: Pillar.News,
128+
display: ArticleDisplay.Standard,
129+
},
130+
'0',
131+
2,
132+
),
133+
trailText:
134+
'From the mock-Tudor fad of the 1920s to drivers refuelling on a roundabout, each era produces its own distinctive petrol stations – as photographer Philip Butler discovered',
135+
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
136+
},
137+
{
138+
url: 'http://localhost:9000/fashion/gallery/2025/aug/22/what-to-wear-to-notting-hill-carnival',
139+
linkText: 'On parade: what to wear to Notting Hill carnival',
140+
showByline: false,
141+
byline: 'Melanie Wilkinson',
142+
image: {
143+
src: 'https://media.guim.co.uk/49a9656cd10c4f64f8bdd54380afb915c7a3648b/207_0_1500_1200/master/1500.jpg',
144+
altText: '',
145+
},
146+
format: {
147+
design: ArticleDesign.Gallery,
148+
theme: Pillar.Lifestyle,
149+
display: ArticleDisplay.Standard,
150+
},
151+
webPublicationDate: '2025-08-22T05:00:23.000Z',
152+
headline: 'On parade: what to wear to Notting Hill carnival',
153+
shortUrl: 'https://www.theguardian.com/p/x32mte',
154+
discussion: {
155+
isCommentable: false,
156+
isClosedForComments: true,
157+
discussionId: '/p/x32mte',
158+
},
159+
dataLinkName: getDataLinkNameCard(
160+
{
161+
design: ArticleDesign.Gallery,
162+
theme: Pillar.Lifestyle,
163+
display: ArticleDisplay.Standard,
164+
},
165+
'0',
166+
1,
167+
),
168+
trailText:
169+
'The Guardian’s picture editors select photographs from around the world',
170+
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for thismainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
171+
},
172+
],
173+
},
174+
} satisfies Story;

0 commit comments

Comments
 (0)