Fields
Built-in field types that can be used to create beautiful forms rapidly with minimal code.
The form.Field
component can be used to create a field for any of these types.
text
,email
,url
,phone
,time
number
password
textarea
select
checkbox
radio
If no type
is provided, the field will default to text
.
Setup
Add FieldsProvider
to your app to make the fields available to all forms.
import { FieldsProvider, defaultFieldTypes } from '@saas-ui/forms'
function MyApp() {
return (
<FieldsProvider value={{ fields: defaultFieldTypes }}>
<App />
</FieldsProvider>
)
Basic usage
import { FormLayout, SubmitButton, useForm } from '@saas-ui/forms'
function MyForm() {
const form = useForm({
defaultValues: {
name: '',
email: '',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field name="name" type="text" />
<form.Field name="email" type="email" />
</FormLayout>
<SubmitButton>Save</SubmitButton>
</form.Form>
)
}
Built-in fields
Text Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormText() {
const form = useForm({
defaultValues: {
name: '',
email: '',
phone: '',
time: '',
url: '',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field name="name" label="Name" type="text" />
<form.Field name="email" label="Email" type="email" />
<form.Field
name="email"
label="Phone"
type="phone"
startElement={'+1'}
/>
<form.Field name="time" label="Time" type="time" />
<form.Field name="url" label="Url" type="url" />
</FormLayout>
</form.Form>
)
}
Number Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormNumber() {
const form = useForm({
defaultValues: {
amount: 0,
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field name="amount" label="Amount" type="number" />
<form.Field
name="amount"
label="Amount (with start element)"
type="number"
startElement={'$'}
/>
<form.Field
name="amount"
label="Amount (no controls)"
type="number"
hideControls
/>
</FormLayout>
</form.Form>
)
}
Password Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormPassword() {
const form = useForm({
defaultValues: {
password: '',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field name="password" label="Password" type="password" />
</FormLayout>
</form.Form>
)
}
Select Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormSelect() {
const form = useForm({
defaultValues: {
color: 'red',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field
name="color"
label="Color"
type="select"
options={[
{ label: 'Red', value: 'red' },
{ label: 'Green', value: 'green' },
{ label: 'Blue', value: 'blue' },
]}
/>
</FormLayout>
</form.Form>
)
}
Checkbox Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormCheckbox() {
const form = useForm({
defaultValues: {
terms: false,
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field
name="terms"
label="Accept terms and conditions"
type="checkbox"
/>
</FormLayout>
</form.Form>
)
}
Radio Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormRadio() {
const form = useForm({
defaultValues: {
color: 'red',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field
name="color"
label="Color"
type="radio"
options={[
{ label: 'Red', value: 'red' },
{ label: 'Green', value: 'green' },
{ label: 'Blue', value: 'blue' },
]}
/>
</FormLayout>
</form.Form>
)
}
Switch Field
'use client'
import { FormLayout, useForm } from '@saas-ui/forms'
export function FormSwitch() {
const form = useForm({
defaultValues: {
notifications: false,
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<FormLayout>
<form.Field
name="notifications"
label="Enable notifications"
type="switch"
/>
</FormLayout>
</form.Form>
)
}
Custom fields
Since useForm
is built on top of react-hook-form
, you can use any of the
react-hook-form API to create custom
fields.
This is useful when you need to create a one off field that is not supported by the built-in fields.
import { Controller, SubmitButton, useForm } from '@saas-ui/forms'
function MyForm() {
const form = useForm({
defaultValues: {
name: '',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<Controller
control={form.control}
name="name"
render={({ field }) => <Input {...field} />}
/>
<SubmitButton>Submit</SubmitButton>
</form.Form>
)
}
To create a re-usable custom field, you can use the createField
function to
define a field type that can be passed to the useForm
hook.
import { createField, useForm } from '@saas-ui/forms'
interface InputFieldProps extends InputProps {
type?: string
startElement?: React.ReactNode
endElement?: React.ReactNode
}
const InputField = createField<HTMLInputElement, InputFieldProps>(
({ type = 'text', startElement, endElement, size, ...rest }, ref) => {
return (
<InputGroup
startElement={startElement}
endElement={endElement}
width="full"
>
<Input type={type} size={size} {...rest} ref={ref} />
</InputGroup>
)
},
)
The createField
function takes two arguments:
- The component to render
- An options object
The options object can be used to configure the field type.
The createField
function returns a React component that can be used to render
the field.
// App.tsx
import { createField, FieldsProvider, defaultFieldTypes } from '@saas-ui/forms'
const CustomInputField = createField<HTMLInputElement, InputFieldProps>(
(props, ref) => {
return <Input {...props} type="text" ref={ref} />
},
)
export default function App() {
return (
<FieldsProvider value={{
fields: {
...defaultFieldTypes
custom: CustomInputField,
}
}}>
<App />
</FieldsProvider>
)
}
// Form.tsx
import { useForm } from '@saas-ui/forms'
function MyForm() {
const form = useForm({
defaultValues: {
name: '',
},
onSubmit: (values) => {
console.log(values)
},
})
return (
<form.Form>
<form.Field name="name" type="custom" />
<SubmitButton>Submit</SubmitButton>
</form.Form>
)
}