Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion dotcom-rendering/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ export const Card = ({
- */
const isMediaCardOrNewsletter = isMediaCard(format) || isNewsletter;

const showPill = isMediaCardOrNewsletter;
const isOnwardRelatedContent = containerType === 'related-content';
const showPill = isMediaCardOrNewsletter && !isOnwardRelatedContent;

const media = getMedia({
imageUrl: image?.src,
Expand Down
43 changes: 27 additions & 16 deletions dotcom-rendering/src/components/FetchOnwardsData.importable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { RenderingTarget } from '../types/renderingTarget';
import type { FETrailType, TrailType } from '../types/trails';
import { Carousel } from './Carousel.importable';
import { Placeholder } from './Placeholder';
import { ScrollableSmallOnwards } from './ScrollableSmallOnwards';

type Props = {
url: string;
Expand Down Expand Up @@ -89,22 +90,32 @@ export const FetchOnwardsData = ({

return (
<div css={minHeight}>
<Carousel
heading={data.heading || data.displayname} // Sometimes the api returns heading as 'displayName'
trails={trails}
description={data.description}
onwardsSource={onwardsSource}
format={format}
leftColSize={
format.design === ArticleDesign.LiveBlog ||
format.design === ArticleDesign.DeadBlog
? 'wide'
: 'compact'
}
discussionApiUrl={discussionApiUrl}
absoluteServerTimes={absoluteServerTimes}
renderingTarget={renderingTarget}
/>
{format.design === ArticleDesign.Gallery ? (
<ScrollableSmallOnwards
absoluteServerTimes={absoluteServerTimes}
trails={trails}
discussionApiUrl={discussionApiUrl}
heading={data.heading || data.displayname}
onwardsSource={onwardsSource}
/>
) : (
<Carousel
heading={data.heading || data.displayname} // Sometimes the api returns heading as 'displayName'
trails={trails}
description={data.description}
onwardsSource={onwardsSource}
format={format}
leftColSize={
format.design === ArticleDesign.LiveBlog ||
format.design === ArticleDesign.DeadBlog
? 'wide'
: 'compact'
}
discussionApiUrl={discussionApiUrl}
absoluteServerTimes={absoluteServerTimes}
renderingTarget={renderingTarget}
/>
)}
</div>
);
};
20 changes: 19 additions & 1 deletion dotcom-rendering/src/components/OnwardsUpper.importable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,20 @@ export const OnwardsUpper = ({
format.design === ArticleDesign.Gallery ? isUndefined(url) : true;

return (
<div css={onwardsWrapper}>
<div id="marjan" css={onwardsWrapper}>
{!!url && (
<Section
fullWidth={true}
borderColour={palette('--article-section-border')}
padSides={
format.design === ArticleDesign.Gallery ? false : true
}
showTopBorder={
format.design === ArticleDesign.Gallery ? false : true
}
showSideBorders={
format.design === ArticleDesign.Gallery ? false : true
}
>
<FetchOnwardsData
url={url}
Expand All @@ -335,6 +344,15 @@ export const OnwardsUpper = ({
<Section
fullWidth={true}
borderColour={palette('--article-section-border')}
showTopBorder={
format.design === ArticleDesign.Gallery ? false : true
}
showSideBorders={
format.design === ArticleDesign.Gallery ? false : true
}
padSides={
format.design === ArticleDesign.Gallery ? false : true
}
>
<FetchOnwardsData
url={curatedDataUrl}
Expand Down
23 changes: 14 additions & 9 deletions dotcom-rendering/src/components/ScrollableCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,34 @@ const itemStyles = css`
position: relative;
`;

const leftBorderStyles = css`
const leftBorderStyles = (isOnwardContent?: boolean) => css`
content: '';
position: absolute;
top: 0;
bottom: 0;
left: -10px;
width: 1px;
background-color: ${palette('--card-border-top')};
background-color: ${isOnwardContent
? palette('--onward-content-border')
: palette('--card-border-top')};
transform: translateX(-50%);
`;

const singleRowLeftBorderStyles = css`
const singleRowLeftBorderStyles = (isOnwardContent?: boolean) => css`
:not(:first-child)::before {
${leftBorderStyles}
${leftBorderStyles(isOnwardContent)}
}
`;

const stackedRowLeftBorderStyles = css`
const stackedRowLeftBorderStyles = (isOnwardContent?: boolean) => css`
${from.tablet} {
:not(:first-child)::before {
${leftBorderStyles}
${leftBorderStyles(isOnwardContent)}
}
}
${until.tablet} {
:not(:first-child):not(:nth-child(2))::before {
${leftBorderStyles}
${leftBorderStyles(isOnwardContent)}
}
}
`;
Expand Down Expand Up @@ -410,17 +412,20 @@ export const ScrollableCarousel = ({

ScrollableCarousel.Item = ({
isStackingCarousel = false,
isOnwardContent = false,
children,
}: {
isStackingCarousel?: boolean;
children: React.ReactNode;
/** The colour of borders can be overriden */
isOnwardContent?: boolean;
}) => (
<li
css={[
itemStyles,
isStackingCarousel
? stackedRowLeftBorderStyles
: singleRowLeftBorderStyles,
? stackedRowLeftBorderStyles(isOnwardContent)
: singleRowLeftBorderStyles(isOnwardContent),
]}
>
{children}
Expand Down
174 changes: 174 additions & 0 deletions dotcom-rendering/src/components/ScrollableSmallOnwards.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import type { Meta, StoryObj } from '@storybook/react';
import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat';
import { getDataLinkNameCard } from '../lib/getDataLinkName';
import { ScrollableSmallOnwards } from './ScrollableSmallOnwards';

const meta = {
title: 'Components/ScrollableSmallOnwards',
component: ScrollableSmallOnwards,
} satisfies Meta<typeof ScrollableSmallOnwards>;

export default meta;

type Story = StoryObj<typeof meta>;

export const ScrollableSmallOnwardsStory = {
args: {
absoluteServerTimes: false,
discussionApiUrl:
'https://discussion.code.dev-theguardian.com/discussion-api',
heading: 'More on this story',
headingUrl: 'http://localhost:9000/more-galleries',
onwardsSource: 'more-galleries',
trails: [
{
url: 'http://localhost:9000/environment/gallery/2025/aug/22/week-in-wildlife-a-clumsy-fox-swinging-orangutang-and-rescued-jaguarundi-cub',
linkText:
'Week in wildlife: a clumsy fox, a swinging orangutan and a rescued jaguarundi cub',
showByline: false,
byline: 'Pejman Faratin',
image: {
src: 'https://media.guim.co.uk/a81e974ffee6c8c88fa280c2d02eaf5dc2af863e/151_292_1020_816/master/1020.jpg',
altText: '',
},
format: {
theme: Pillar.News,
design: ArticleDesign.Gallery,
display: ArticleDisplay.Standard,
},
webPublicationDate: '2022-01-01T06:00:25.000Z',
headline:
'Week in wildlife: a clumsy fox, a swinging orangutan and a rescued jaguarundi cub',
shortUrl: 'https://www.theguardian.com/p/x32n89',
discussion: {
isCommentable: false,
isClosedForComments: true,
discussionId: '/p/x32n89',
},
discussionId: 'zHoBy6HNKsk',
dataLinkName: getDataLinkNameCard(
{
theme: Pillar.News,
design: ArticleDesign.Gallery,
display: ArticleDisplay.Standard,
},
'0',
0,
),
trailText:
'Guinness World Records is looking back at the extraordinary feats achieved since its inception - as well as unveiling 70 whacky and unclaimed records ',
kickerText: 'Politics', // Get data for this
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
},
{
url: 'http://localhost:9000/money/gallery/2025/aug/22/characterful-cottages-for-sale-in-england-in-pictures',
linkText:
'Characterful cottages for sale in England – in pictures',
showByline: false,
byline: 'Anna White',
image: {
src: 'https://media.guim.co.uk/58cd9356e6d68e8efa6028162bb959f9798307d5/515_0_5000_4000/master/5000.jpg',
altText: '',
},
format: {
design: ArticleDesign.Gallery,
theme: Pillar.Lifestyle,
display: ArticleDisplay.Standard,
},
webPublicationDate: '2022-01-01T06:00:24.000Z',
headline:
'Characterful cottages for sale in England – in pictures',
shortUrl: 'https://www.theguardian.com/p/x32gqj',
discussion: {
isCommentable: false,
isClosedForComments: true,
discussionId: '/p/x32gqj',
},
dataLinkName: getDataLinkNameCard(
{
design: ArticleDesign.Gallery,
theme: Pillar.Lifestyle,
display: ArticleDisplay.Standard,
},
'0',
1,
),
trailText:
'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',
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
},
{
url: 'http://localhost:9000/news/gallery/2025/aug/22/sunsets-aid-parachutes-and-giant-pandas-photos-of-the-day-friday',
linkText:
'Sunsets, aid parachutes and giant pandas: photos of the day – Friday ',
showByline: false,
byline: 'Eithne Staunton',
image: {
src: 'https://media.guim.co.uk/4ce0b080206fe9b65b976c1acf219d81072cc814/0_0_2113_1690/master/2113.png',
altText: '',
},
format: {
design: ArticleDesign.Gallery,
theme: Pillar.News,
display: ArticleDisplay.Standard,
},
webPublicationDate: '2022-01-01T08:49:42.000Z',
headline:
'Sunsets, aid parachutes and giant pandas: photos of the day – Friday ',
shortUrl: 'https://www.theguardian.com/p/x3359z',
discussion: {
isCommentable: false,
isClosedForComments: true,
discussionId: '/p/x3359z',
},
dataLinkName: getDataLinkNameCard(
{
design: ArticleDesign.Gallery,
theme: Pillar.News,
display: ArticleDisplay.Standard,
},
'0',
2,
),
trailText:
'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',
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
},
{
url: 'http://localhost:9000/fashion/gallery/2025/aug/22/what-to-wear-to-notting-hill-carnival',
linkText: 'On parade: what to wear to Notting Hill carnival',
showByline: false,
byline: 'Melanie Wilkinson',
image: {
src: 'https://media.guim.co.uk/49a9656cd10c4f64f8bdd54380afb915c7a3648b/207_0_1500_1200/master/1500.jpg',
altText: '',
},
format: {
design: ArticleDesign.Gallery,
theme: Pillar.Lifestyle,
display: ArticleDisplay.Standard,
},
webPublicationDate: '2025-08-22T05:00:23.000Z',
headline: 'On parade: what to wear to Notting Hill carnival',
shortUrl: 'https://www.theguardian.com/p/x32mte',
discussion: {
isCommentable: false,
isClosedForComments: true,
discussionId: '/p/x32mte',
},
dataLinkName: getDataLinkNameCard(
{
design: ArticleDesign.Gallery,
theme: Pillar.Lifestyle,
display: ArticleDisplay.Standard,
},
'0',
1,
),
trailText:
'The Guardian’s picture editors select photographs from around the world',
mainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for thismainMedia: { type: 'Gallery', count: '6' }, // TODO: get data for this
},
],
},
} satisfies Story;
Loading
Loading