Skip to content

Commit f264865

Browse files
docs: adding ui libraries intergration docs and example (#536)
* docs: adding ui libraries intergration docs and example * chore(docs): created guides under react and example for ui components * chore: add PNPM lock updates * chore: pass test * chore: format --------- Co-authored-by: Corbin Crutchley <[email protected]>
1 parent 567e38b commit f264865

15 files changed

+1624
-1026
lines changed

docs/config.json

+13
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@
7070
}
7171
]
7272
},
73+
{
74+
"label": "Guides",
75+
"children": [
76+
{
77+
"label": "UI Libraries",
78+
"to": "framework/react/guides/ui-libraries"
79+
}
80+
]
81+
},
7382
{
7483
"label": "API Reference",
7584
"children": [
@@ -109,6 +118,10 @@
109118
{
110119
"label": "Valibot",
111120
"to": "framework/react/examples/valibot"
121+
},
122+
{
123+
"label": "UI Libraries",
124+
"to": "framework/react/examples/ui-libraries"
112125
}
113126
]
114127
}
+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
---
2+
id: ui-libraries
3+
title: UI Libraries
4+
---
5+
6+
# Usage of TanStack Form with UI Libraries
7+
8+
TanStack Form is a headless library, offering you complete flexibility to style it as you see fit. It's compatible with a wide range of UI libraries, including `Tailwind`, `Material-UI`, `Mantine`, or even plain CSS.
9+
10+
This guide focuses on `Material-UI` and `Mantine`, but the concepts are applicable to any UI library of your choice.
11+
12+
## Prerequisites
13+
14+
Before integrating TanStack Form with a UI library, ensure the necessary dependencies are installed in your project:
15+
16+
- For `Material-UI`, follow the installation instructions on their [official site](https://mui.com/material-ui/getting-started/).
17+
- For `Mantine`, refer to their [documentation](https://mantine.dev/).
18+
19+
Note: While you can mix and match libraries, it's generally advisable to stick with one to maintain consistency and minimize bloat.
20+
21+
## Example with Mantine
22+
23+
Here's an example demonstrating the integration of TanStack Form with Mantine components:
24+
25+
```tsx
26+
import { TextInput, Checkbox } from '@mantine/core'
27+
import { useForm } from '@tanstack/react-form'
28+
29+
export default function App() {
30+
const { Provider, Field, handleSubmit, state } = useForm({
31+
defaultValues: {
32+
firstName: '',
33+
lastName: '',
34+
isChecked: false,
35+
},
36+
onSubmit: async ({ value }) => {
37+
// Handle form submission
38+
console.log(value)
39+
},
40+
})
41+
42+
return (
43+
<>
44+
<Provider>
45+
<form
46+
onSubmit={(e) => {
47+
e.preventDefault()
48+
handleSubmit()
49+
}}
50+
>
51+
<Field
52+
name="firstName"
53+
children={({ state, handleChange, handleBlur }) => (
54+
<TextInput
55+
defaultValue={state.value}
56+
onChange={(e) => handleChange(e.target.value)}
57+
onBlur={handleBlur}
58+
placeholder="Enter your name"
59+
/>
60+
)}
61+
/>
62+
<Field
63+
name="isChecked"
64+
children={({ state, handleChange, handleBlur }) => (
65+
<Checkbox
66+
onChange={(e) => handleChange(e.target.checked)}
67+
onBlur={handleBlur}
68+
checked={state.value}
69+
/>
70+
)}
71+
/>
72+
</form>
73+
</Provider>
74+
<div>
75+
<pre>{JSON.stringify(state.values, null, 2)}</pre>
76+
</div>
77+
</>
78+
)
79+
}
80+
```
81+
82+
- Initially, we utilize the `useForm` hook from TanStack and destructure the necessary properties. This step is optional; alternatively, you could use `const form = useForm()` if preferred. TypeScript's type inference ensures a smooth experience regardless of the approach.
83+
- Next, we encapsulate our form elements within the `Provider` component, a critical step for enabling form functionalities. The `Field` component, derived from `useForm`, accepts several properties, such as `validators`. For this demonstration, we focus on two primary properties: `name` and `children`.
84+
- The `name` property identifies each `Field`, for instance, `firstName` in our example.
85+
- The `children` property leverages the concept of render props, allowing us to integrate components without unnecessary abstractions.
86+
- TanStack's design relies heavily on render props, providing access to `children` within the `Field` component. This approach is entirely type-safe. When integrating with Mantine components, such as `TextInput`, we selectively destructure properties like `state.value`, `handleChange`, and `handleBlur`. This selective approach is due to the slight differences in types between `TextInput` and the `field` we get in the children.
87+
- By following these steps, you can seamlessly integrate Mantine components with TanStack Form.
88+
- This methodology is equally applicable to other components, such as `Checkbox`, ensuring consistent integration across different UI elements.
89+
90+
## Usage with `Material-UI`
91+
92+
The process for integrating Material-UI components is similar. Here's an example using TextField and Checkbox from Material-UI:
93+
94+
```tsx
95+
<Field
96+
name="lastName"
97+
children={({ state, handleChange, handleBlur }) => {
98+
return (
99+
<TextField
100+
id="filled-basic"
101+
label="Filled"
102+
variant="filled"
103+
defaultValue={state.value}
104+
onChange={(e) => handleChange(e.target.value)}
105+
onBlur={handleBlur}
106+
placeholder="Enter your last name"
107+
/>
108+
);
109+
}}
110+
/>
111+
112+
<Field
113+
name="isMuiCheckBox"
114+
children={({ state, handleChange, handleBlur }) => {
115+
return (
116+
<MuiCheckbox
117+
onChange={(e) => handleChange(e.target.checked)}
118+
onBlur={handleBlur}
119+
checked={state.value}
120+
/>
121+
);
122+
}}
123+
/>
124+
125+
```
126+
127+
- The integration approach is the same as with Mantine.
128+
- The primary difference lies in the specific Material-UI component properties and styling options.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @ts-check
2+
3+
/** @type {import('eslint').Linter.Config} */
4+
const config = {
5+
env: { browser: true, es2020: true },
6+
extends: [
7+
'eslint:recommended',
8+
'plugin:@typescript-eslint/recommended',
9+
'plugin:react-hooks/recommended',
10+
],
11+
parser: '@typescript-eslint/parser',
12+
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
13+
plugins: ['react-refresh'],
14+
rules: {
15+
'react-refresh/only-export-components': 'warn',
16+
},
17+
}
18+
19+
module.exports = config
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
pnpm-lock.yaml
15+
yarn.lock
16+
package-lock.json
17+
18+
# misc
19+
.DS_Store
20+
.env.local
21+
.env.development.local
22+
.env.test.local
23+
.env.production.local
24+
25+
npm-debug.log*
26+
yarn-debug.log*
27+
yarn-error.log*
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

examples/react/ui-libraries/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Example
2+
3+
To run this example:
4+
5+
- `npm install`
6+
- `npm run dev`
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" type="image/svg+xml" href="/emblem-light.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
9+
<title>TanStack Form React With UI MUI and Mantine</title>
10+
</head>
11+
<body>
12+
<noscript>You need to enable JavaScript to run this app.</noscript>
13+
<div id="root"></div>
14+
<script type="module" src="./src/index.tsx"></script>
15+
</body>
16+
</html>
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"name": "@tanstack/form-example-react-ui-libraries",
3+
"version": "0.0.1",
4+
"main": "src/index.jsx",
5+
"scripts": {
6+
"dev": "vite --port=3001",
7+
"build": "vite build",
8+
"preview": "vite preview",
9+
"test:types": "tsc --noEmit"
10+
},
11+
"dependencies": {
12+
"@emotion/react": "11.11.3",
13+
"@emotion/styled": "11.11.0",
14+
"@mantine/core": "7.3.2",
15+
"@mantine/hooks": "7.3.2",
16+
"@mui/material": "5.15.2",
17+
"@tanstack/react-form": "0.11.0",
18+
"@yme/lay-postcss": "0.1.0",
19+
"postcss": "8.4.32",
20+
"postcss-preset-mantine": "1.12.2",
21+
"postcss-simple-vars": "7.0.1",
22+
"react": "^18.2.0",
23+
"react-dom": "^18.2.0"
24+
},
25+
"devDependencies": {
26+
"@types/react": "^18.2.45",
27+
"@types/react-dom": "^18.2.18",
28+
"@typescript-eslint/eslint-plugin": "^6.15.0",
29+
"@typescript-eslint/parser": "^6.15.0",
30+
"@vitejs/plugin-react": "4.2.1",
31+
"@vitejs/plugin-react-swc": "^3.5.0",
32+
"eslint": "^8.56.0",
33+
"eslint-plugin-react": "^7.33.2",
34+
"eslint-plugin-react-hooks": "^4.6.0",
35+
"eslint-plugin-react-refresh": "^0.4.5",
36+
"typescript": "^5.3.3",
37+
"vite": "^5.0.10"
38+
},
39+
"browserslist": {
40+
"production": [
41+
">0.2%",
42+
"not dead",
43+
"not op_mini all"
44+
],
45+
"development": [
46+
"last 1 chrome version",
47+
"last 1 firefox version",
48+
"last 1 safari version"
49+
]
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
plugins: {
3+
'postcss-preset-mantine': {},
4+
'postcss-simple-vars': {
5+
variables: {
6+
'mantine-breakpoint-xs': '36em',
7+
'mantine-breakpoint-sm': '48em',
8+
'mantine-breakpoint-md': '62em',
9+
'mantine-breakpoint-lg': '75em',
10+
'mantine-breakpoint-xl': '88em',
11+
},
12+
},
13+
},
14+
}

0 commit comments

Comments
 (0)