Skip to content

Commit e7f32e3

Browse files
(Admin) Jonathan Ruda(Admin) Jonathan Ruda
authored andcommitted
Adds ManyNewslettersFormFields.tsx to improve readability and cleans up theme props
1 parent fcb0e31 commit e7f32e3

File tree

2 files changed

+133
-111
lines changed

2 files changed

+133
-111
lines changed

dotcom-rendering/src/components/ManyNewslettersForm.tsx

Lines changed: 16 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,18 @@ import {
55
palette,
66
space,
77
} from '@guardian/source/foundations';
8-
import {
9-
Button,
10-
Checkbox,
11-
CheckboxGroup,
12-
TextInput,
13-
} from '@guardian/source/react-components';
8+
import { Button } from '@guardian/source/react-components';
149
import {
1510
type ChangeEventHandler,
1611
type ReactEventHandler,
1712
useState,
1813
} from 'react';
19-
import ReactGoogleRecaptcha from 'react-google-recaptcha';
14+
import type ReactGoogleRecaptcha from 'react-google-recaptcha';
2015
import { InlineSkipToWrapper } from './InlineSkipToWrapper';
16+
import { ManyNewslettersFormFields } from './ManyNewslettersFormFields';
2117
import { NewsletterPrivacyMessage } from './NewsletterPrivacyMessage';
2218

23-
interface FormProps {
19+
export interface FormProps {
2420
status: 'NotSent' | 'Loading' | 'Success' | 'Failed' | 'InvalidEmail';
2521
email: string;
2622
handleTextInput: ChangeEventHandler<HTMLInputElement>;
@@ -71,29 +67,6 @@ const formFieldsStyle = css`
7167
}
7268
`;
7369

74-
const inputWrapperStyle = css`
75-
margin-bottom: ${space[2]}px;
76-
${from.desktop} {
77-
margin-bottom: 0;
78-
margin-right: ${space[2]}px;
79-
flex-basis: 296px;
80-
}
81-
`;
82-
83-
const inputAndOptInWrapperStyle = css`
84-
${from.desktop} {
85-
flex-basis: 296px;
86-
margin-right: ${space[2]}px;
87-
}
88-
`;
89-
90-
const optInCheckboxTextSmall = css`
91-
label > div {
92-
font-size: 13px;
93-
line-height: 16px;
94-
}
95-
`;
96-
9770
const formAsideStyle = (hideOnMobile: boolean) => css`
9871
overflow: hidden;
9972
transition: max-height 1.5s linear;
@@ -155,24 +128,13 @@ export const ManyNewslettersForm = ({
155128
handleCaptchaError,
156129
}: FormProps) => {
157130
const [formHasFocus, setFormHasFocus] = useState(false);
158-
const [firstInteractionOccurred, setFirstInteractionOccurred] =
159-
useState(false);
160131
const hidePrivacyOnMobile = !formHasFocus && email.length === 0;
161132

162-
const isMarketingOptInVisible = marketingOptIn !== undefined;
163-
164133
const ariaLabel =
165134
newsletterCount === 1
166135
? 'Sign up for the newsletter you selected'
167136
: `Sign up for the ${newsletterCount} newsletters you selected`;
168137

169-
const errorMessage =
170-
status === 'Failed'
171-
? 'Sign up failed. Please try again'
172-
: status === 'InvalidEmail'
173-
? 'Please enter a valid email address'
174-
: undefined;
175-
176138
return (
177139
<form
178140
aria-label="sign-up confirmation form"
@@ -200,75 +162,18 @@ export const ManyNewslettersForm = ({
200162
<div css={formFieldsStyle}>
201163
{status !== 'Success' ? (
202164
<>
203-
<div css={inputAndOptInWrapperStyle}>
204-
<span css={inputWrapperStyle}>
205-
<TextInput
206-
label="Enter your email"
207-
value={email}
208-
onChange={handleTextInput}
209-
error={errorMessage}
210-
disabled={status === 'Loading'}
211-
onFocus={() =>
212-
setFirstInteractionOccurred(true)
213-
}
214-
/>
215-
</span>
216-
{isMarketingOptInVisible && (
217-
<div>
218-
<CheckboxGroup
219-
name="marketing-preferences"
220-
label="Marketing preferences"
221-
hideLabel={true}
222-
cssOverrides={optInCheckboxTextSmall}
223-
>
224-
<Checkbox
225-
label="Get updates about our journalism and ways to support and enjoy our work."
226-
value="marketing-opt-in"
227-
checked={marketingOptIn}
228-
onChange={(e) =>
229-
setMarketingOptIn(
230-
e.target.checked,
231-
)
232-
}
233-
theme={{
234-
fillUnselected:
235-
palette.neutral[100],
236-
borderUnselected:
237-
palette.neutral[46],
238-
fillSelected:
239-
palette.brand[500],
240-
borderSelected:
241-
palette.brand[500],
242-
borderHover: palette.brand[500],
243-
}}
244-
/>
245-
</CheckboxGroup>
246-
</div>
247-
)}
248-
{useReCaptcha && !!captchaSiteKey && (
249-
<div
250-
css={css`
251-
.grecaptcha-badge {
252-
visibility: hidden;
253-
}
254-
`}
255-
>
256-
{(!visibleRecaptcha ||
257-
firstInteractionOccurred) && (
258-
<ReactGoogleRecaptcha
259-
sitekey={captchaSiteKey}
260-
ref={reCaptchaRef}
261-
onError={handleCaptchaError}
262-
size={
263-
visibleRecaptcha
264-
? 'normal'
265-
: 'invisible'
266-
}
267-
/>
268-
)}
269-
</div>
270-
)}
271-
</div>
165+
<ManyNewslettersFormFields
166+
status={status}
167+
email={email}
168+
handleTextInput={handleTextInput}
169+
marketingOptIn={marketingOptIn}
170+
setMarketingOptIn={setMarketingOptIn}
171+
useReCaptcha={useReCaptcha}
172+
captchaSiteKey={captchaSiteKey}
173+
visibleRecaptcha={visibleRecaptcha}
174+
reCaptchaRef={reCaptchaRef}
175+
handleCaptchaError={handleCaptchaError}
176+
/>
272177
<Button
273178
aria-label={ariaLabel}
274179
isLoading={status === 'Loading'}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { css } from '@emotion/react';
2+
import { from, palette, space } from '@guardian/source/foundations';
3+
import {
4+
Checkbox,
5+
CheckboxGroup,
6+
TextInput,
7+
} from '@guardian/source/react-components';
8+
import type { FC } from 'react';
9+
import { useState } from 'react';
10+
import ReactGoogleRecaptcha from 'react-google-recaptcha';
11+
import type { FormProps } from './ManyNewslettersForm';
12+
13+
const inputWrapperStyle = css`
14+
margin-bottom: ${space[2]}px;
15+
${from.desktop} {
16+
margin-bottom: 0;
17+
margin-right: ${space[2]}px;
18+
flex-basis: 296px;
19+
}
20+
`;
21+
22+
const inputAndOptInWrapperStyle = css`
23+
${from.desktop} {
24+
flex-basis: 296px;
25+
margin-right: ${space[2]}px;
26+
}
27+
`;
28+
29+
const optInCheckboxTextSmall = css`
30+
label > div {
31+
font-size: 13px;
32+
line-height: 16px;
33+
}
34+
`;
35+
36+
export interface ManyNewslettersFormFieldsProps
37+
extends Omit<FormProps, 'handleSubmitButton' | 'newsletterCount'> {}
38+
39+
export const ManyNewslettersFormFields: FC<ManyNewslettersFormFieldsProps> = ({
40+
status,
41+
email,
42+
handleTextInput,
43+
marketingOptIn,
44+
setMarketingOptIn,
45+
useReCaptcha,
46+
captchaSiteKey,
47+
visibleRecaptcha,
48+
reCaptchaRef,
49+
handleCaptchaError,
50+
}) => {
51+
const [firstInteractionOccurred, setFirstInteractionOccurred] =
52+
useState(false);
53+
54+
const isMarketingOptInVisible = marketingOptIn !== undefined;
55+
56+
const errorMessage =
57+
status === 'Failed'
58+
? 'Sign up failed. Please try again'
59+
: status === 'InvalidEmail'
60+
? 'Please enter a valid email address'
61+
: undefined;
62+
63+
return (
64+
<div css={inputAndOptInWrapperStyle}>
65+
<span css={inputWrapperStyle}>
66+
<TextInput
67+
label="Enter your email"
68+
value={email}
69+
onChange={handleTextInput}
70+
error={errorMessage}
71+
disabled={status === 'Loading'}
72+
onFocus={() => setFirstInteractionOccurred(true)}
73+
/>
74+
</span>
75+
{isMarketingOptInVisible && (
76+
<div>
77+
<CheckboxGroup
78+
name="marketing-preferences"
79+
label="Marketing preferences"
80+
hideLabel={true}
81+
cssOverrides={optInCheckboxTextSmall}
82+
>
83+
<Checkbox
84+
label="Get updates about our journalism and ways to support and enjoy our work."
85+
value="marketing-opt-in"
86+
checked={marketingOptIn}
87+
onChange={(e) =>
88+
setMarketingOptIn(e.target.checked)
89+
}
90+
theme={{
91+
fillUnselected: palette.neutral[100],
92+
}}
93+
/>
94+
</CheckboxGroup>
95+
</div>
96+
)}
97+
{useReCaptcha && !!captchaSiteKey && (
98+
<div
99+
css={css`
100+
.grecaptcha-badge {
101+
visibility: hidden;
102+
}
103+
`}
104+
>
105+
{(!visibleRecaptcha || firstInteractionOccurred) && (
106+
<ReactGoogleRecaptcha
107+
sitekey={captchaSiteKey}
108+
ref={reCaptchaRef}
109+
onError={handleCaptchaError}
110+
size={visibleRecaptcha ? 'normal' : 'invisible'}
111+
/>
112+
)}
113+
</div>
114+
)}
115+
</div>
116+
);
117+
};

0 commit comments

Comments
 (0)