chore: add Storybook stories for MyForm component

This commit is contained in:
2026-09-19 16:59:28 +03:30
parent 107624d4f2
commit 12f8b70c2b
3 changed files with 308 additions and 3 deletions
+186
View File
@@ -0,0 +1,186 @@
import React from "react";
import { useForm } from "@tanstack/react-form";
export function MyForm() {
const form = useForm({
defaultValues: {
username: "",
age: "",
password: "",
},
onSubmit: async ({ value }) => {
console.log("Form submitted successfully:", value);
alert(JSON.stringify(value, null, 2));
},
});
return (
<div
style={{
maxWidth: "400px",
margin: "20px auto",
fontFamily: "sans-serif",
}}
>
<h2>Registration Form (TanStack Form)</h2>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
form.handleSubmit();
}}
>
<form.Field
name="username"
validators={{
onChange: ({ value }) => {
if (!value) return "Full name is required";
if (!/^[a-zA-Za-z\s]+$/.test(value)) {
return "Please enter letters only";
}
return undefined;
},
}}
>
{(field) => (
<div style={{ marginBottom: "15px" }}>
<label
htmlFor={field.name}
style={{ display: "block", marginBottom: "5px" }}
>
Full Name (Letters only):
</label>
<input
id={field.name}
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
style={{
width: "100%",
padding: "8px",
boxSizing: "border-box",
}}
/>
{field.state.meta.errors.length > 0 && (
<span style={{ color: "red", fontSize: "12px" }}>
{field.state.meta.errors.join(", ")}
</span>
)}
</div>
)}
</form.Field>
<form.Field
name="age"
validators={{
onChange: ({ value }) => {
if (!value) return "Age is required";
if (isNaN(Number(value))) {
return "Please enter numbers only";
}
if (Number(value) < 18) {
return "Age must be at least 18";
}
return undefined;
},
}}
>
{(field) => (
<div style={{ marginBottom: "15px" }}>
<label
htmlFor={field.name}
style={{ display: "block", marginBottom: "5px" }}
>
Age (Numbers only):
</label>
<input
id={field.name}
name={field.name}
type="number"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
style={{
width: "100%",
padding: "8px",
boxSizing: "border-box",
}}
/>
{field.state.meta.errors.length > 0 && (
<span style={{ color: "red", fontSize: "12px" }}>
{field.state.meta.errors.join(", ")}
</span>
)}
</div>
)}
</form.Field>
<form.Field
name="password"
validators={{
onChange: ({ value }) => {
if (!value) return "Password is required";
if (value.length < 8) {
return "Password must be at least 8 characters long";
}
return undefined;
},
}}
>
{(field) => (
<div style={{ marginBottom: "15px" }}>
<label
htmlFor={field.name}
style={{ display: "block", marginBottom: "5px" }}
>
Password:
</label>
<input
id={field.name}
name={field.name}
type="password"
value={field.state.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
style={{
width: "100%",
padding: "8px",
boxSizing: "border-box",
}}
/>
{field.state.meta.errors.length > 0 && (
<span style={{ color: "red", fontSize: "12px" }}>
{field.state.meta.errors.join(", ")}
</span>
)}
</div>
)}
</form.Field>
<form.Subscribe
selector={(state) => [state.canSubmit, state.isSubmitting]}
>
{([canSubmit, isSubmitting]) => (
<button
type="submit"
disabled={!canSubmit}
style={{
width: "100%",
padding: "10px",
backgroundColor: canSubmit ? "#007bff" : "#ccc",
color: "white",
border: "none",
borderRadius: "4px",
cursor: canSubmit ? "pointer" : "not-allowed",
}}
>
{isSubmitting ? "Submitting..." : "Sign Up"}
</button>
)}
</form.Subscribe>
</form>
</div>
);
}