Skip to content

Commit 425a03b

Browse files
committed
Add Most Viewed Front Right
1 parent ad5d9e7 commit 425a03b

3 files changed

Lines changed: 202 additions & 4 deletions

File tree

dotcom-rendering/src/components/LinkHeadline.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
headlineMedium20,
66
headlineMedium24,
77
headlineMedium28,
8+
textSans15,
89
textSans17,
910
textSans20,
1011
textSans24,
@@ -33,9 +34,23 @@ type Props = {
3334
size?: SmallHeadlineSize;
3435
link?: HeadlineLink; // An optional link object configures if/how the component renders an anchor tag
3536
byline?: string;
37+
/**
38+
* This headline is being used on the right-hand side of a front in a most popular container,
39+
* either Most Viewed or Deeply Read, as part of the Slim Homepage AB test.
40+
*/
41+
isInSlimHomepageAbTest?: boolean;
3642
};
3743

38-
const fontStyles = (size: SmallHeadlineSize) => {
44+
const fontStyles = (
45+
size: SmallHeadlineSize,
46+
isInSlimHomepageAbTest: boolean,
47+
) => {
48+
if (isInSlimHomepageAbTest) {
49+
return css`
50+
${textSans15};
51+
`;
52+
}
53+
3954
switch (size) {
4055
case 'ginormous':
4156
case 'huge':
@@ -124,9 +139,10 @@ export const LinkHeadline = ({
124139
size = 'medium',
125140
link,
126141
byline,
142+
isInSlimHomepageAbTest = false,
127143
}: Props) => {
128144
return (
129-
<h4 css={[fontStyles(size)]}>
145+
<h4 css={[fontStyles(size, isInSlimHomepageAbTest)]}>
130146
{!!kickerText && (
131147
<Kicker
132148
text={kickerText}
@@ -160,7 +176,7 @@ export const LinkHeadline = ({
160176
fontStyles={
161177
isLabs
162178
? bylineLabsStyles(size)
163-
: fontStyles(size)
179+
: fontStyles(size, isInSlimHomepageAbTest)
164180
}
165181
text={byline}
166182
/>
@@ -175,7 +191,7 @@ export const LinkHeadline = ({
175191
fontStyles={
176192
isLabs
177193
? bylineLabsStyles(size)
178-
: fontStyles(size)
194+
: fontStyles(size, isInSlimHomepageAbTest)
179195
}
180196
text={byline}
181197
/>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
2+
import { rightColumnDecorator } from '../../.storybook/decorators/gridDecorators';
3+
import { trails } from '../../fixtures/manual/trails';
4+
import { MostPopularFrontRight } from './MostPopularFrontRight';
5+
6+
const meta = {
7+
component: MostPopularFrontRight,
8+
title: 'Components/MostPopularFrontRight',
9+
decorators: [rightColumnDecorator],
10+
render: (args) => <MostPopularFrontRight {...args} />,
11+
} satisfies Meta<typeof MostPopularFrontRight>;
12+
13+
export default meta;
14+
15+
type Story = StoryObj<typeof meta>;
16+
17+
export const MostViewed = {
18+
args: {
19+
heading: 'Most viewed',
20+
trails: trails.slice(0, 10),
21+
},
22+
} satisfies Story;
23+
24+
export const DeeplyRead = {
25+
args: {
26+
heading: 'Deeply read',
27+
trails: trails.slice(10, 20),
28+
},
29+
} satisfies Story;
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { css } from '@emotion/react';
2+
import {
3+
headlineBold24,
4+
space,
5+
textSans15,
6+
} from '@guardian/source/foundations';
7+
import { ArticleDesign, ArticleSpecial } from '../lib/articleFormat';
8+
import { palette as schemePalette } from '../palette';
9+
import type { TrailType } from '../types/trails';
10+
import { AgeWarning } from './AgeWarning';
11+
import { BigNumber } from './BigNumber';
12+
import { FormatBoundary } from './FormatBoundary';
13+
import { LinkHeadline } from './LinkHeadline';
14+
15+
const containerStyles = css`
16+
padding-top: ${space[2]}px;
17+
display: flex;
18+
flex-direction: column;
19+
gap: ${space[8]}px;
20+
`;
21+
22+
const headingStyles = css`
23+
padding-left: 80px;
24+
${headlineBold24};
25+
color: ${schemePalette('--slim-homepage-most-viewed-header')};
26+
overflow-wrap: break-word;
27+
`;
28+
29+
const gridItem = css`
30+
position: relative;
31+
border-top: 1px solid ${schemePalette('--article-section-border')};
32+
min-height: 52px;
33+
34+
&:hover {
35+
cursor: pointer;
36+
}
37+
38+
&:hover,
39+
:focus {
40+
background: ${schemePalette('--most-viewed-footer-hover')};
41+
}
42+
`;
43+
44+
const bigNumber = css`
45+
position: absolute;
46+
top: 6px;
47+
left: 10px;
48+
fill: ${schemePalette('--slim-homepage-most-viewed-big-number')};
49+
svg {
50+
height: 40px;
51+
}
52+
`;
53+
54+
const headlineLink = css`
55+
display: block; /* To ensure focus outline works okay */
56+
padding: 3px 10px 18px 80px;
57+
${textSans15};
58+
text-decoration: none;
59+
color: #000;
60+
font-weight: 500;
61+
word-wrap: break-word;
62+
overflow: hidden;
63+
`;
64+
65+
const ageWarningStyles = css`
66+
padding-left: 75px;
67+
margin-top: -16px;
68+
margin-bottom: 16px;
69+
`;
70+
71+
type Props = {
72+
heading: 'Most viewed' | 'Deeply read';
73+
trails: TrailType[];
74+
};
75+
76+
/**
77+
* Renders the Most Viewed or Deeply Read component, often seen at the bottom of the page on
78+
* network front, into a newly created right column high up on a front page. This component is
79+
* only used as a part of an ongoing AB test and should not be used outside of this AB test.
80+
*/
81+
export const MostPopularFrontRight = ({ heading, trails }: Props) => {
82+
if (trails.length === 0) return null;
83+
84+
return (
85+
<section
86+
data-component="most-popular-front-right"
87+
css={containerStyles}
88+
>
89+
<h3 css={headingStyles}>{heading}</h3>
90+
<ol>
91+
{trails.slice(0, 10).map((trail: TrailType, index: number) => {
92+
const { url, format, headline, ageWarning } = trail;
93+
94+
return (
95+
<li css={gridItem} key={url}>
96+
<a
97+
css={headlineLink}
98+
href={url}
99+
data-link-name={`article | ${index + 1}`}
100+
>
101+
<span css={bigNumber}>
102+
<BigNumber index={index + 1} />
103+
</span>
104+
<FormatBoundary format={format}>
105+
{format.design ===
106+
ArticleDesign.LiveBlog ? (
107+
<LinkHeadline
108+
headlineText={headline}
109+
isLabs={
110+
format.theme ===
111+
ArticleSpecial.Labs
112+
}
113+
size="small"
114+
kickerText="Live"
115+
hasInlineKicker={false}
116+
showPulsingDot={true}
117+
showQuotes={false}
118+
isInSlimHomepageAbTest={true}
119+
/>
120+
) : (
121+
<LinkHeadline
122+
headlineText={headline}
123+
isLabs={
124+
format.theme ===
125+
ArticleSpecial.Labs
126+
}
127+
size="small"
128+
showQuotes={
129+
format.design ===
130+
ArticleDesign.Comment ||
131+
format.design ===
132+
ArticleDesign.Letter
133+
}
134+
isInSlimHomepageAbTest={true}
135+
/>
136+
)}
137+
</FormatBoundary>
138+
{!!ageWarning && (
139+
<div css={ageWarningStyles}>
140+
<AgeWarning
141+
age={ageWarning}
142+
size="small"
143+
/>
144+
</div>
145+
)}
146+
</a>
147+
</li>
148+
);
149+
})}
150+
</ol>
151+
</section>
152+
);
153+
};

0 commit comments

Comments
 (0)