Skip to content

Commit feb997f

Browse files
Merge branch 'main' into upgrade-node
2 parents 4f1a1a0 + afe98a3 commit feb997f

13 files changed

+145
-23
lines changed

dotcom-rendering/src/components/FlexibleSpecial.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const determineCardProperties = (
8787
imageSize: 'jumbo',
8888
supportingContentAlignment:
8989
supportingContentLength >= 3 ? 'horizontal' : 'vertical',
90-
liveUpdatesAlignment: 'horizontal',
90+
liveUpdatesAlignment: 'vertical',
9191
trailTextSize: 'regular',
9292
};
9393
case 'megaboost':

dotcom-rendering/src/components/ScrollableCarousel.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Props = {
1111
visibleCardsOnMobile: number;
1212
visibleCardsOnTablet: number;
1313
sectionId?: string;
14+
shouldStackCards?: { desktop: boolean; mobile: boolean };
1415
};
1516

1617
/**
@@ -103,6 +104,20 @@ const itemStyles = css`
103104
}
104105
`;
105106

107+
const stackedCardRowsStyles = ({
108+
mobile,
109+
desktop,
110+
}: {
111+
mobile: boolean;
112+
desktop: boolean;
113+
}) => css`
114+
grid-template-rows: ${mobile ? `1fr 1fr` : `1fr`};
115+
${from.tablet} {
116+
grid-auto-flow: ${desktop ? `row` : `column`};
117+
grid-template-rows: ${desktop ? `1fr 1fr` : `1fr`};
118+
}
119+
`;
120+
106121
/**
107122
* Generates CSS styles for a grid layout used in a carousel.
108123
*
@@ -168,6 +183,7 @@ export const ScrollableCarousel = ({
168183
visibleCardsOnMobile,
169184
visibleCardsOnTablet,
170185
sectionId,
186+
shouldStackCards = { desktop: false, mobile: false },
171187
}: Props) => {
172188
const carouselRef = useRef<HTMLOListElement | null>(null);
173189
const [previousButtonEnabled, setPreviousButtonEnabled] = useState(false);
@@ -253,6 +269,7 @@ export const ScrollableCarousel = ({
253269
visibleCardsOnMobile,
254270
visibleCardsOnTablet,
255271
),
272+
stackedCardRowsStyles(shouldStackCards),
256273
]}
257274
data-heatphan-type="carousel"
258275
>

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ export const ScrollableSmall = ({
3535
aspectRatio,
3636
sectionId,
3737
}: Props) => {
38+
const mobileBottomCards = [1, 3];
39+
const desktopBottomCards = [2, 3];
3840
return (
3941
<ScrollableCarousel
40-
carouselLength={trails.length}
42+
carouselLength={Math.ceil(trails.length / 2)}
4143
visibleCardsOnMobile={1}
4244
visibleCardsOnTablet={2}
4345
sectionId={sectionId}
46+
shouldStackCards={{ desktop: trails.length > 2, mobile: true }}
4447
>
45-
{trails.map((trail) => {
48+
{trails.map((trail, index) => {
4649
return (
4750
<ScrollableCarousel.Item key={trail.url}>
4851
<FrontCard
@@ -64,8 +67,10 @@ export const ScrollableSmall = ({
6467
aspectRatio={aspectRatio}
6568
kickerText={trail.kickerText}
6669
showLivePlayable={trail.showLivePlayable}
67-
showTopBarDesktop={false}
68-
showTopBarMobile={false}
70+
showTopBarDesktop={desktopBottomCards.includes(
71+
index,
72+
)}
73+
showTopBarMobile={mobileBottomCards.includes(index)}
6974
canPlayInline={false}
7075
/>
7176
</ScrollableCarousel.Item>

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ export default meta;
4343

4444
type Story = StoryObj<typeof ScrollableSmall>;
4545

46-
export const WithMultipleCards = {};
47-
4846
export const WithFourCards = {
4947
args: {
5048
trails: trails.slice(0, 4),
@@ -57,15 +55,15 @@ export const WithThreeCards = {
5755
},
5856
};
5957

60-
export const WithOneCard = {
58+
export const WithTwoCards = {
6159
args: {
62-
trails: trails.slice(0, 1),
60+
trails: trails.slice(0, 2),
6361
},
6462
};
6563

66-
export const WithTwoCards = {
64+
export const WithOneCard = {
6765
args: {
68-
trails: trails.slice(0, 2),
66+
trails: trails.slice(0, 1),
6967
},
7068
};
7169

dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBannerV2.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,11 @@ const DesignableBannerV2: ReactComponent<BannerRenderProps> = ({
450450
}
451451
choices={getChoiceCardData(
452452
isTabletOrAbove,
453+
false,
453454
countryCode,
454455
)}
455456
id={'banner'}
457+
isDiscountActive={false}
456458
/>
457459

458460
<div css={styles.ctaContainer}>

dotcom-rendering/src/components/marketing/epics/ContributionsEpic.stories.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,25 @@ export const WithThreeTierDiscountChoiceCards: Story = {
349349
},
350350
};
351351

352+
export const WithThreeTierDiscountChoiceCardsNonUS: Story = {
353+
name: 'ContributionsEpic with discounted three tier choice cards For Non US',
354+
args: {
355+
...meta.args,
356+
countryCode: 'GB',
357+
variant: {
358+
...props.variant,
359+
name: 'THREE_TIER_CHOICE_CARDS',
360+
secondaryCta: undefined,
361+
showChoiceCards: true,
362+
cta: {
363+
text: 'Support the Guardian',
364+
baseUrl:
365+
'https://support.theguardian.com/uk/contribute?promoCode=30OFFAPRIL',
366+
},
367+
},
368+
},
369+
};
370+
352371
export const WithChoiceCardsAndSignInLink: Story = {
353372
name: 'ContributionsEpic with choice cards and sign-in link',
354373
args: {

dotcom-rendering/src/components/marketing/epics/ThreeTierChoiceCardData.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import type { ChoiceInfo } from './ThreeTierChoiceCards';
33

44
export const ChoiceCardTestData_REGULAR = (
55
longerBenefits: boolean,
6+
isDiscountActive: boolean,
67
): ChoiceInfo[] => [
78
{
89
supportTier: 'Contribution',
910
label: (amount: number, currencySymbol: string): string =>
10-
`Support ${currencySymbol}${amount}/month`,
11+
isDiscountActive
12+
? `Support ${currencySymbol}${amount}/year`
13+
: `Support ${currencySymbol}${amount}/month`,
1114
benefitsLabel: 'Support',
1215
benefits: () => [
1316
'Exclusive newsletter for supporters, sent every week from the Guardian newsroom',
@@ -30,7 +33,7 @@ export const ChoiceCardTestData_REGULAR = (
3033
{amount}
3134
</s>{' '}
3235
{currencySymbol}
33-
{amount * discount}/month{' '}
36+
{amount * (1 - discount)}/year{' '}
3437
</>
3538
);
3639
} else {

dotcom-rendering/src/components/marketing/epics/ThreeTierChoiceCards.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ type ThreeTierChoiceCardsProps = {
184184
choices: ChoiceInfo[];
185185
supporterPlusDiscount?: number;
186186
id: string; // uniquely identify this choice cards component to avoid conflicting with others
187+
isDiscountActive: boolean;
187188
};
188189

189190
export const ThreeTierChoiceCards = ({
@@ -193,6 +194,7 @@ export const ThreeTierChoiceCards = ({
193194
choices,
194195
supporterPlusDiscount,
195196
id,
197+
isDiscountActive = false,
196198
}: ThreeTierChoiceCardsProps) => {
197199
const currencySymbol = getLocalCurrencySymbol(countryCode);
198200
const countryGroupId = countryCodeToCountryGroupId(countryCode);
@@ -217,6 +219,12 @@ export const ThreeTierChoiceCards = ({
217219
'Monthly',
218220
countryGroupId,
219221
);
222+
const choiceAmountYearly = getChoiceAmount(
223+
supportTier,
224+
'Annual',
225+
countryGroupId,
226+
);
227+
220228
const selected = selectedProduct === supportTier;
221229

222230
const hasDiscount =
@@ -225,6 +233,10 @@ export const ThreeTierChoiceCards = ({
225233

226234
const radioId = `choicecard-${id}-${supportTier}`;
227235

236+
const finalChoiceAmount = isDiscountActive
237+
? choiceAmountYearly
238+
: choiceAmount;
239+
228240
return (
229241
<div
230242
key={supportTier}
@@ -246,7 +258,7 @@ export const ThreeTierChoiceCards = ({
246258
>
247259
<Radio
248260
label={label(
249-
choiceAmount,
261+
finalChoiceAmount,
250262
currencySymbol,
251263
supporterPlusDiscount,
252264
)}

dotcom-rendering/src/components/marketing/epics/ctas/ContributionsEpicButtons.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ interface ContributionsEpicButtonsProps {
150150
amountsTestName?: string;
151151
amountsVariantName?: string;
152152
numArticles: number;
153+
isDiscountActive?: boolean;
153154
}
154155

155156
export const ContributionsEpicButtons = ({
@@ -165,6 +166,7 @@ export const ContributionsEpicButtons = ({
165166
amountsTestName,
166167
amountsVariantName,
167168
numArticles,
169+
isDiscountActive,
168170
}: ContributionsEpicButtonsProps): JSX.Element | null => {
169171
const [hasBeenSeen, setNode] = useIsInView({
170172
debounce: true,
@@ -187,16 +189,33 @@ export const ContributionsEpicButtons = ({
187189
}
188190

189191
const getChoiceCardCta = (cta: Cta): Cta => {
192+
const countryGroupId = countryCodeToCountryGroupId(countryCode);
190193
if (showChoiceCards) {
191194
if (threeTierChoiceCardSelectedProduct === 'OneOff') {
192195
return {
193196
text: cta.text,
194197
baseUrl: addChoiceCardsOneTimeParams(cta.baseUrl),
195198
};
196199
}
200+
if (isDiscountActive) {
201+
const contributionAmount =
202+
threeTierChoiceCardSelectedProduct === 'SupporterPlus'
203+
? threeTierChoiceCardAmounts['Annual'][countryGroupId]
204+
.SupporterPlus
205+
: undefined;
206+
207+
return {
208+
text: cta.text,
209+
baseUrl: addChoiceCardsProductParams(
210+
cta.baseUrl,
211+
threeTierChoiceCardSelectedProduct,
212+
'Annual',
213+
contributionAmount,
214+
),
215+
};
216+
}
197217

198218
/** Contribution amount is variable, unlike the SupporterPlus amount which is fixed */
199-
const countryGroupId = countryCodeToCountryGroupId(countryCode);
200219
const contributionAmount =
201220
threeTierChoiceCardSelectedProduct === 'Contribution'
202221
? threeTierChoiceCardAmounts['Monthly'][countryGroupId]

dotcom-rendering/src/components/marketing/epics/ctas/ContributionsEpicCtasContainer.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface OnReminderOpen {
1414
type Props = EpicProps & {
1515
amountsTestName?: string;
1616
amountsVariantName?: string;
17+
now?: Date;
1718
};
1819

1920
export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
@@ -26,6 +27,7 @@ export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
2627
fetchEmail,
2728
amountsTestName,
2829
amountsVariantName,
30+
now = new Date(),
2931
}: Props): JSX.Element => {
3032
// reminders
3133
const [fetchedEmail, setFetchedEmail] = useState<string | undefined>(
@@ -53,8 +55,15 @@ export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
5355
setThreeTierChoiceCardSelectedProduct,
5456
] = useState<SupportTier>('SupporterPlus');
5557

56-
const hasSupporterPlusPromoCode =
57-
variant.cta?.baseUrl.includes('BLACK_FRIDAY_DISCOUNT_2024') ?? false;
58+
const hasPromoCodeInUrl =
59+
variant.cta?.baseUrl.includes('30OFFAPRIL') ?? false;
60+
61+
// Check the dates
62+
const isDiscountActive =
63+
(hasPromoCodeInUrl &&
64+
now >= new Date('2025-04-15T00:00:01') &&
65+
now < new Date('2025-04-21T23:59:59')) ??
66+
false;
5867

5968
return (
6069
<>
@@ -63,11 +72,14 @@ export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
6372
countryCode={countryCode}
6473
selectedProduct={threeTierChoiceCardSelectedProduct}
6574
setSelectedProduct={setThreeTierChoiceCardSelectedProduct}
66-
choices={getChoiceCardData(true, countryCode)}
67-
supporterPlusDiscount={
68-
hasSupporterPlusPromoCode ? 0.5 : undefined
69-
}
75+
choices={getChoiceCardData(
76+
true,
77+
isDiscountActive,
78+
countryCode,
79+
)}
80+
supporterPlusDiscount={isDiscountActive ? 0.3 : undefined}
7081
id={'epic'}
82+
isDiscountActive={isDiscountActive}
7183
/>
7284
)}
7385
<ContributionsEpicButtons
@@ -108,6 +120,7 @@ export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
108120
amountsTestName={amountsTestName}
109121
amountsVariantName={amountsVariantName}
110122
numArticles={articleCounts.for52Weeks}
123+
isDiscountActive={isDiscountActive}
111124
/>
112125
{isReminderActive && showReminderFields && (
113126
<ContributionsEpicReminder

0 commit comments

Comments
 (0)