Skip to content

Commit 2aab326

Browse files
committed
Create Form component to de-duplicate styling for forms
1 parent 26451c4 commit 2aab326

File tree

4 files changed

+42
-20
lines changed

4 files changed

+42
-20
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { ComponentChildren } from 'preact';
2+
import type { JSX } from 'preact';
3+
4+
export type FormProps = JSX.FormHTMLAttributes & {
5+
/**
6+
* CSRF token to render in a hidden field.
7+
*
8+
* If the form is not going to be submitted to the backend directly, for
9+
* example because the frontend is going to make API requests instead, this
10+
* can be set to `null`. This prop is required so that callers have to make
11+
* an explicit choice.
12+
*/
13+
csrfToken: string | null;
14+
15+
children: ComponentChildren;
16+
};
17+
18+
/**
19+
* Wrapper around an HTML form which adds standard styling, CSRF token etc.
20+
*/
21+
export default function Form({ children, csrfToken, ...formAttrs }: FormProps) {
22+
return (
23+
<form
24+
method="POST"
25+
data-testid="form"
26+
className="max-w-[530px] mx-auto flex flex-col gap-y-4"
27+
{...formAttrs}
28+
>
29+
{csrfToken && <input type="hidden" name="csrf_token" value={csrfToken} />}
30+
{children}
31+
</form>
32+
);
33+
}

h/static/scripts/group-forms/components/CreateEditGroupForm.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useContext, useEffect, useId, useState } from 'preact/hooks';
99

1010
import Checkbox from '../../forms-common/components/Checkbox';
1111
import ErrorNotice from '../../forms-common/components/ErrorNotice';
12+
import Form from '../../forms-common/components/Form';
1213
import FormContainer from '../../forms-common/components/FormContainer';
1314
import Label from '../../forms-common/components/Label';
1415
import Star from '../../forms-common/components/Star';
@@ -242,11 +243,7 @@ export default function CreateEditGroupForm({
242243
return (
243244
<FormContainer>
244245
<GroupFormHeader group={group} title={heading} />
245-
<form
246-
onSubmit={onSubmit}
247-
data-testid="form"
248-
className="max-w-[530px] mx-auto flex flex-col gap-y-4"
249-
>
246+
<Form onSubmit={onSubmit} csrfToken={null}>
250247
<TextField
251248
type="input"
252249
value={name}
@@ -335,7 +332,7 @@ export default function CreateEditGroupForm({
335332
{group ? 'Save changes' : 'Create group'}
336333
</Button>
337334
</div>
338-
</form>
335+
</Form>
339336

340337
{group && pendingGroupType && (
341338
<GroupTypeChangeWarning

h/static/scripts/login-forms/components/LoginForm.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Button, Link } from '@hypothesis/frontend-shared';
22
import { useContext } from 'preact/hooks';
33

4+
import Form from '../../forms-common/components/Form';
45
import FormContainer from '../../forms-common/components/FormContainer';
56
import TextField from '../../forms-common/components/TextField';
67
import { useFormValue } from '../../forms-common/form-value';
@@ -20,12 +21,7 @@ export default function LoginForm() {
2021

2122
return (
2223
<FormContainer>
23-
<form
24-
method="POST"
25-
data-testid="form"
26-
className="max-w-[530px] mx-auto flex flex-col gap-y-4"
27-
>
28-
<input type="hidden" name="csrf_token" value={config.csrfToken} />
24+
<Form csrfToken={config.csrfToken}>
2925
<TextField
3026
type="input"
3127
name="username"
@@ -74,7 +70,7 @@ export default function LoginForm() {
7470
Log in
7571
</Button>
7672
</div>
77-
</form>
73+
</Form>
7874
</FormContainer>
7975
);
8076
}

h/static/scripts/login-forms/components/SignupForm.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Button } from '@hypothesis/frontend-shared';
22
import { useContext } from 'preact/hooks';
33

44
import Checkbox from '../../forms-common/components/Checkbox';
5+
import Form from '../../forms-common/components/Form';
56
import FormContainer from '../../forms-common/components/FormContainer';
67
import TextField from '../../forms-common/components/TextField';
78
import { useFormValue } from '../../forms-common/form-value';
@@ -39,12 +40,7 @@ export default function SignupForm() {
3940

4041
return (
4142
<FormContainer>
42-
<form
43-
method="POST"
44-
data-testid="form"
45-
className="max-w-[530px] mx-auto flex flex-col gap-y-4"
46-
>
47-
<input type="hidden" name="csrf_token" value={config.csrfToken} />
43+
<Form csrfToken={config.csrfToken}>
4844
<TextField
4945
type="input"
5046
name="username"
@@ -130,7 +126,7 @@ export default function SignupForm() {
130126
Sign up
131127
</Button>
132128
</div>
133-
</form>
129+
</Form>
134130
</FormContainer>
135131
);
136132
}

0 commit comments

Comments
 (0)