Skip to content

Commit 2882b48

Browse files
committed
refactor(InformationBox): combine the terms box, and the grey box on the email sent page into a single component
1 parent 0cc4dbc commit 2882b48

8 files changed

+151
-114
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import { Meta } from '@storybook/react';
3+
4+
import { InformationBoxText, InformationBox } from './InformationBox';
5+
import { ButtonLink, Link } from '@guardian/source-react-components';
6+
import { ExternalLink } from './ExternalLink';
7+
8+
export default {
9+
title: 'Components/InformationBox',
10+
component: InformationBox,
11+
} as Meta;
12+
13+
export const Default = () => (
14+
<InformationBox>
15+
<InformationBoxText>
16+
This is some useful stuff in the information box
17+
</InformationBoxText>
18+
<InformationBoxText>
19+
And some more useful stuff in the information box but this one is a{' '}
20+
<Link href="#">link</Link>.
21+
</InformationBoxText>
22+
<InformationBoxText>
23+
This also works with <ExternalLink href="#">external links</ExternalLink>{' '}
24+
too. As well as <ButtonLink>buttons that look like links</ButtonLink>.
25+
</InformationBoxText>
26+
</InformationBox>
27+
);
28+
Default.storyName = 'default';
29+
30+
export const WithMarginTop = () => (
31+
<InformationBox withMarginTop>
32+
<InformationBoxText>
33+
This is some useful stuff in the information box, with a margin top!
34+
</InformationBoxText>
35+
<InformationBoxText>
36+
And some more useful stuff in the information box but this one is a{' '}
37+
<Link href="#">link</Link>.
38+
</InformationBoxText>
39+
<InformationBoxText>
40+
This also works with <ExternalLink href="#">external links</ExternalLink>{' '}
41+
too. As well as <ButtonLink>buttons that look like links</ButtonLink>.
42+
</InformationBoxText>
43+
</InformationBox>
44+
);
45+
WithMarginTop.storyName = 'withMarginTop';
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { PropsWithChildren } from 'react';
2+
import { css } from '@emotion/react';
3+
import { palette, space, textSans } from '@guardian/source-foundations';
4+
5+
interface InformationBoxProps {
6+
withMarginTop?: boolean;
7+
}
8+
9+
const informationBoxStyles = ({ withMarginTop }: InformationBoxProps) => css`
10+
background-color: ${palette.neutral[93]};
11+
border-radius: 4px;
12+
padding: ${space[3]}px ${space[3]}px;
13+
${withMarginTop && `margin-top: ${space[5]}px;`}
14+
`;
15+
16+
const informationBoxTextStyle = css`
17+
${textSans.xsmall()}
18+
margin: 0 0 ${space[2]}px 0;
19+
&:last-of-type {
20+
margin: 0;
21+
}
22+
23+
a {
24+
${textSans.xsmall()}
25+
}
26+
27+
button {
28+
${textSans.xsmall()}
29+
}
30+
`;
31+
export const InformationBoxText = ({
32+
children,
33+
}: {
34+
children: React.ReactNode;
35+
}) => <div css={informationBoxTextStyle}>{children}</div>;
36+
37+
export const InformationBox = ({
38+
children,
39+
withMarginTop,
40+
}: PropsWithChildren<InformationBoxProps>) => (
41+
<div css={informationBoxStyles({ withMarginTop })}>{children}</div>
42+
);

src/client/components/MainForm.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ import {
1313
GuardianTerms,
1414
JobsTerms,
1515
RecaptchaTerms,
16-
TermsBox,
17-
TermsText,
1816
} from '@/client/components/Terms';
1917
import { space } from '@guardian/source-foundations';
2018
import { buttonStyles } from '@/client/layouts/Main';
@@ -29,6 +27,7 @@ import { trackFormFocusBlur, trackFormSubmit } from '@/client/lib/ophan';
2927
import { logger } from '@/client/lib/clientSideLogger';
3028
import { ErrorSummary } from '@guardian/source-react-components-development-kitchen';
3129
import locations from '@/shared/lib/locations';
30+
import { InformationBox, InformationBoxText } from './InformationBox';
3231

3332
export interface MainFormProps {
3433
formAction: string;
@@ -61,7 +60,7 @@ export interface MainFormProps {
6160
largeFormMarginTop?: boolean;
6261
submitButtonLink?: boolean;
6362
hideRecaptchaMessage?: boolean;
64-
additionalTerms?: string;
63+
additionalTerms?: ReactNode;
6564
}
6665

6766
const formStyles = (
@@ -317,12 +316,14 @@ export const MainForm = ({
317316
hasGuardianTerms ||
318317
hasJobsTerms ||
319318
(recaptchaEnabled && !hideRecaptchaMessage)) && (
320-
<TermsBox>
319+
<InformationBox>
321320
{hasGuardianTerms && <GuardianTerms />}
322321
{hasJobsTerms && <JobsTerms />}
323-
{additionalTerms && <TermsText>{additionalTerms}</TermsText>}
322+
{additionalTerms && (
323+
<InformationBoxText>{additionalTerms}</InformationBoxText>
324+
)}
324325
{recaptchaEnabled && !hideRecaptchaMessage && <RecaptchaTerms />}
325-
</TermsBox>
326+
</InformationBox>
326327
)}
327328

328329
{submitButtonLink ? (
+6-5
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
import React from 'react';
22
import { Meta } from '@storybook/react';
33

4-
import { GuardianTerms, JobsTerms, RecaptchaTerms, TermsBox } from './Terms';
4+
import { GuardianTerms, JobsTerms, RecaptchaTerms } from './Terms';
5+
import { InformationBox } from './InformationBox';
56

67
export default {
78
title: 'Components/Terms',
89
component: GuardianTerms,
910
} as Meta;
1011

1112
export const Default = () => (
12-
<TermsBox>
13+
<InformationBox>
1314
<GuardianTerms />
1415
<RecaptchaTerms />
15-
</TermsBox>
16+
</InformationBox>
1617
);
1718

1819
Default.storyName = 'Terms';
1920

2021
export const Jobs = () => (
21-
<TermsBox>
22+
<InformationBox>
2223
<JobsTerms />
2324
<RecaptchaTerms />
24-
</TermsBox>
25+
</InformationBox>
2526
);
2627

2728
Jobs.storyName = 'Jobs terms';

src/client/components/Terms.tsx

+21-63
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,45 @@
1-
import React, { PropsWithChildren } from 'react';
2-
import { css } from '@emotion/react';
3-
import { palette, space, textSans } from '@guardian/source-foundations';
4-
import { ExternalLink } from '@/client/components/ExternalLink';
5-
6-
interface TermsProps {
7-
withMarginTop?: boolean;
8-
}
9-
10-
const termsBoxStyle = ({ withMarginTop }: TermsProps) => css`
11-
background-color: ${palette.neutral[93]};
12-
border-radius: 4px;
13-
padding: ${space[3]}px ${space[3]}px;
14-
${withMarginTop && `margin-top: ${space[5]}px;`}
15-
`;
16-
17-
const termsBoxTextStyle = css`
18-
${textSans.xsmall()}
19-
margin: 0 0 ${space[2]}px 0;
20-
&:last-of-type {
21-
margin: 0;
22-
}
23-
`;
24-
25-
export const TermsText = ({ children }: { children: React.ReactNode }) => (
26-
<p css={termsBoxTextStyle}>{children}</p>
27-
);
28-
29-
const TermsLink = ({ children, href }: PropsWithChildren<{ href: string }>) => (
30-
<ExternalLink
31-
cssOverrides={css`
32-
${textSans.xsmall()}
33-
`}
34-
href={href}
35-
>
36-
{children}
37-
</ExternalLink>
38-
);
39-
40-
export const TermsBox = ({
41-
children,
42-
withMarginTop,
43-
}: PropsWithChildren<TermsProps>) => (
44-
<div css={termsBoxStyle({ withMarginTop })}>{children}</div>
45-
);
1+
import React from 'react';
2+
import { InformationBoxText } from './InformationBox';
3+
import { ExternalLink } from './ExternalLink';
464

475
export const GuardianTerms = () => (
48-
<TermsText>
6+
<InformationBoxText>
497
By proceeding, you agree to our{' '}
50-
<TermsLink href="https://www.theguardian.com/help/terms-of-service">
8+
<ExternalLink href="https://www.theguardian.com/help/terms-of-service">
519
terms &amp; conditions
52-
</TermsLink>
10+
</ExternalLink>
5311
. For information about how we use your data, see our{' '}
54-
<TermsLink href="https://www.theguardian.com/help/privacy-policy">
12+
<ExternalLink href="https://www.theguardian.com/help/privacy-policy">
5513
privacy policy
56-
</TermsLink>
14+
</ExternalLink>
5715
.
58-
</TermsText>
16+
</InformationBoxText>
5917
);
6018

6119
export const JobsTerms = () => (
62-
<TermsText>
20+
<InformationBoxText>
6321
By proceeding, you agree to our{' '}
64-
<TermsLink href="https://jobs.theguardian.com/terms-and-conditions/">
22+
<ExternalLink href="https://jobs.theguardian.com/terms-and-conditions/">
6523
Guardian Jobs terms &amp; conditions
66-
</TermsLink>
24+
</ExternalLink>
6725
. For information about how we use your data, see our{' '}
68-
<TermsLink href="https://jobs.theguardian.com/privacy-policy/">
26+
<ExternalLink href="https://jobs.theguardian.com/privacy-policy/">
6927
Guardian Jobs privacy policy
70-
</TermsLink>
28+
</ExternalLink>
7129
.
72-
</TermsText>
30+
</InformationBoxText>
7331
);
7432

7533
export const RecaptchaTerms = () => (
76-
<TermsText>
34+
<InformationBoxText>
7735
This service is protected by reCAPTCHA and the Google{' '}
78-
<TermsLink href="https://policies.google.com/privacy">
36+
<ExternalLink href="https://policies.google.com/privacy">
7937
privacy policy
80-
</TermsLink>{' '}
38+
</ExternalLink>{' '}
8139
and{' '}
82-
<TermsLink href="https://policies.google.com/terms">
40+
<ExternalLink href="https://policies.google.com/terms">
8341
terms of service
84-
</TermsLink>{' '}
42+
</ExternalLink>{' '}
8543
apply.
86-
</TermsText>
44+
</InformationBoxText>
8745
);

src/client/pages/EmailSent.tsx

+22-34
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import { MainBodyText } from '@/client/components/MainBodyText';
55
import { MainForm } from '@/client/components/MainForm';
66
import { EmailInput } from '@/client/components/EmailInput';
77
import { ExternalLink } from '@/client/components/ExternalLink';
8-
import { css } from '@emotion/react';
98
import { buildUrl } from '@/shared/lib/routeUtils';
109
import locations from '@/shared/lib/locations';
1110
import { SUPPORT_EMAIL } from '@/shared/model/Configuration';
12-
import { palette, space, textSans } from '@guardian/source-foundations';
11+
import {
12+
InformationBox,
13+
InformationBoxText,
14+
} from '@/client/components/InformationBox';
1315

1416
type Props = {
1517
email?: string;
@@ -25,16 +27,6 @@ type Props = {
2527
instructionContext?: string;
2628
};
2729

28-
const helpBoxStyles = () => css`
29-
background-color: ${palette.neutral[93]};
30-
border-radius: 4px;
31-
padding: ${space[3]}px ${space[3]}px;
32-
33-
& button {
34-
${textSans.small()};
35-
}
36-
`;
37-
3830
export const EmailSent = ({
3931
email,
4032
changeEmailPage,
@@ -83,8 +75,8 @@ export const EmailSent = ({
8375
For your security, the link in the email will expire in 60 minutes.
8476
</b>
8577
</MainBodyText>
86-
<div css={helpBoxStyles}>
87-
<MainBodyText smallText>
78+
<InformationBox>
79+
<InformationBoxText>
8880
Didn’t get the email? Check your spam
8981
{email && resendEmailAction && (
9082
<>
@@ -115,28 +107,24 @@ export const EmailSent = ({
115107
</>
116108
)}
117109
.
118-
</MainBodyText>
110+
</InformationBoxText>
119111
{noAccountInfo && (
120-
<div>
121-
<MainBodyText smallText>
122-
If you don’t receive an email within 2 minutes you may not have an
123-
account. Don’t have an account?{' '}
124-
<Link href={`${buildUrl('/register')}${queryString}`}>
125-
Register for free
126-
</Link>
127-
.
128-
</MainBodyText>
129-
</div>
112+
<InformationBoxText>
113+
If you don’t receive an email within 2 minutes you may not have an
114+
account. Don’t have an account?{' '}
115+
<Link href={`${buildUrl('/register')}${queryString}`}>
116+
Register for free
117+
</Link>
118+
.
119+
</InformationBoxText>
130120
)}
131-
<div>
132-
<MainBodyText smallText noMarginBottom>
133-
For further assistance, email our customer service team at{' '}
134-
<ExternalLink href={locations.SUPPORT_EMAIL_MAILTO}>
135-
{SUPPORT_EMAIL}
136-
</ExternalLink>
137-
</MainBodyText>
138-
</div>
139-
</div>
121+
<InformationBoxText>
122+
For further assistance, email our customer service team at{' '}
123+
<ExternalLink href={locations.SUPPORT_EMAIL_MAILTO}>
124+
{SUPPORT_EMAIL}
125+
</ExternalLink>
126+
</InformationBoxText>
127+
</InformationBox>
140128
</MainLayout>
141129
);
142130
};

src/client/pages/Registration.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import { MainLayout } from '@/client/layouts/Main';
44
import { generateSignInRegisterTabs } from '@/client/components/Nav';
55
import { AuthProviderButtons } from '@/client/components/AuthProviderButtons';
66
import { usePageLoadOphanInteraction } from '@/client/lib/hooks/usePageLoadOphanInteraction';
7-
import { GuardianTerms, JobsTerms, TermsBox } from '@/client/components/Terms';
7+
import { GuardianTerms, JobsTerms } from '@/client/components/Terms';
88
import { Link } from '@guardian/source-react-components';
99
import { Divider } from '@guardian/source-react-components-development-kitchen';
1010
import { MainBodyText } from '@/client/components/MainBodyText';
1111
import { divider } from '@/client/styles/Shared';
1212
import { buildUrlWithQueryParams } from '@/shared/lib/routeUtils';
13+
import { InformationBox } from '@/client/components/InformationBox';
1314

1415
export type RegistrationProps = {
1516
email?: string;
@@ -19,10 +20,10 @@ export type RegistrationProps = {
1920
};
2021

2122
const RegistrationTerms = ({ isJobs }: { isJobs: boolean }) => (
22-
<TermsBox withMarginTop>
23+
<InformationBox withMarginTop>
2324
{!isJobs && <GuardianTerms />}
2425
{isJobs && <JobsTerms />}
25-
</TermsBox>
26+
</InformationBox>
2627
);
2728

2829
export const Registration = ({ queryParams }: RegistrationProps) => {

0 commit comments

Comments
 (0)