Skip to content

Commit f49e7f1

Browse files
committed
Styled form example
1 parent 3e87cda commit f49e7f1

File tree

6 files changed

+125
-18
lines changed

6 files changed

+125
-18
lines changed

Todo.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
- Combine array helpers into one object? This is usefull to pass to other components
66
- Require index for array fields
77
- Add React.forwardRef to input elements
8+
- Pass FormEvent through form.handleSubmit's handler

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"react-router-dom": "^5.2.0",
2323
"react-scripts": "link:../node_modules/react-scripts",
2424
"styled-components": "^5.2.1",
25+
"typed-object-validator": "^1.0.1",
2526
"typed-react-form": "link:..",
2627
"typescript": "link:../node_modules/typescript",
2728
"yup": "^0.32.8"

example/src/StyledForm.tsx

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import React from "react";
2+
import styled from "styled-components";
3+
import { FormError, FormInput, StyledFix, useForm } from "typed-react-form";
4+
import tv, { SchemaType } from "typed-object-validator";
5+
6+
// https://github.com/styled-components/styled-components/issues/1349#issuecomment-375293558
7+
8+
const Container = styled.div`
9+
height: 100vh;
10+
/* background: #0001; */
11+
display: flex;
12+
justify-content: center;
13+
align-items: center;
14+
`;
15+
16+
const Title = styled.div`
17+
padding: 1.5rem;
18+
border-bottom: 1px solid #0002;
19+
font-size: 1.3rem;
20+
font-weight: bold;
21+
`;
22+
23+
const FormContainer = styled.div`
24+
background: white;
25+
border-radius: 0.25em;
26+
box-shadow: 3px 3px 15px 3px #0002;
27+
28+
min-width: 300px;
29+
`;
30+
31+
const Form = styled.form`
32+
padding: 1.5em;
33+
display: grid;
34+
gap: 0.8em;
35+
align-items: center;
36+
grid-template-columns: 100px 1fr;
37+
`;
38+
39+
const StyledButton = styled.button`
40+
cursor: pointer;
41+
appearance: none;
42+
padding: 0.5em 1em;
43+
background: #e22;
44+
color: white;
45+
font-weight: bold;
46+
border: none;
47+
border-radius: 0.3em;
48+
font-size: inherit;
49+
font-family: inherit;
50+
transition: 100ms;
51+
52+
&:hover {
53+
transition: 100ms;
54+
background: #e22d;
55+
}
56+
`;
57+
58+
// Must specify type explicitly
59+
const StyledInput: StyledFix<typeof FormInput> = styled(FormInput)`
60+
border: 2px solid #0002;
61+
border-radius: 0.3em;
62+
padding: 0.5em;
63+
outline: none;
64+
65+
&.typed-form-error {
66+
border-color: red;
67+
}
68+
69+
&.typed-form-dirty {
70+
border-color: #0005;
71+
}
72+
`;
73+
74+
// You can also just use typeof without StyledFix, but this does not support additional styled properties
75+
const StyledError: typeof FormError = styled(FormError)`
76+
font-weight: bold;
77+
color: red;
78+
margin: 0.1em 0;
79+
grid-column: 2;
80+
`;
81+
82+
const FormDataSchema = tv.object({
83+
name: tv.string().min(1),
84+
email: tv.email("Invalid email").min(1)
85+
});
86+
type FormData = SchemaType<typeof FormDataSchema>;
87+
88+
export function StyledForm() {
89+
const form = useForm<FormData>({ name: "", email: "" }, (values) => FormDataSchema.validate(values) ?? ({} as any));
90+
91+
function submit() {
92+
console.log(form.values);
93+
alert(JSON.stringify(form.values, null, 2));
94+
}
95+
96+
return (
97+
<Container>
98+
<FormContainer>
99+
<Title>
100+
Form using <a href="https://styled-components.com/">styled-components</a>
101+
</Title>
102+
<Form onSubmit={form.handleSubmit(submit)}>
103+
<label>Name</label>
104+
<StyledInput form={form} name="name" />
105+
<StyledError form={form} name="name" />
106+
<label>Email</label>
107+
<StyledInput form={form} name="email" />
108+
<StyledError form={form} name="email" />
109+
<StyledButton type="submit" style={{ gridColumn: "span 2" }}>
110+
Submit
111+
</StyledButton>
112+
</Form>
113+
</FormContainer>
114+
</Container>
115+
);
116+
}

example/src/StyledProblem.tsx

Lines changed: 0 additions & 18 deletions
This file was deleted.

example/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import App from "./App";
66
import OneOfObjectForm from "./OneOfObjectForm";
77
import OneOfObjectArrayForm from "./OneOfObjectArrayForm";
88
import { BrowserRouter, Route, Switch } from "react-router-dom";
9+
import { StyledForm } from "./StyledForm";
910

1011
function Router() {
1112
return (
1213
<BrowserRouter>
1314
<Switch>
1415
<Route path="/object-types" component={OneOfObjectForm} />
1516
<Route path="/object-types-array" component={OneOfObjectArrayForm} />
17+
<Route path="/styled-form" component={StyledForm} />
1618
<Route path="/" component={App} />
1719
</Switch>
1820
</BrowserRouter>

example/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10308,6 +10308,11 @@ type@^2.0.0:
1030810308
resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f"
1030910309
integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==
1031010310

10311+
typed-object-validator@^1.0.1:
10312+
version "1.0.1"
10313+
resolved "https://registry.yarnpkg.com/typed-object-validator/-/typed-object-validator-1.0.1.tgz#524184eec5da5a37a90ea3011877b05189e9faee"
10314+
integrity sha512-6h0PJeLVW7J9O65HqgotnDxatlwY652+kuA+yU3CPtJTlP+TJAmLHQ4NrqXwSqnwvNTfd54OuUCTrV6if7g+Mw==
10315+
1031110316
"typed-react-form@link:..":
1031210317
version "0.0.0"
1031310318
uid ""

0 commit comments

Comments
 (0)