Form
Form is a component used to group multiple form elements.
interface Data {
email: string
name: string
password: string
}
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Header>
<Form.Title>Create an account</Form.Title>
<Form.Description>Create an account to get started.</Form.Description>
</Form.Header>
<Form.Body>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Body>
<Form.Footer>
<Form.SubmitButton>Submit</Form.SubmitButton>
</Form.Footer>
</Form.Root>
)
Usage
import { Form } from "@yamada-ui/react"
import { Form } from "@/components/ui"
import { Form } from "@workspaces/ui"
<Form.Root>
<Form.Header>
<Form.Title />
<Form.Description />
</Form.Header>
<Form.Body>
<Form.Group />
</Form.Body>
<Form.Footer>
<Form.SubmitButton />
</Form.Footer>
</Form.Root>
Use props
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Change Variant
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<VStack>
<For each={["plain", "elevated", "outline", "panel"]}>
{(variant, key) => (
<Form.Root
key={key}
variant={variant}
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Fieldset.Root legend="Personal information">
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Fieldset.Root>
</Form.Root>
)}
</For>
</VStack>
)
Change Size
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<VStack>
<For each={["sm", "md", "lg"]}>
{(size, key) => (
<Form.Root
key={key}
size={size}
variant="panel"
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Fieldset.Root legend="Personal information">
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Fieldset.Root>
</Form.Root>
)}
</For>
</VStack>
)
Displaying a Helper Message
To display a helper message, set a {[key: string]: ReactNode} to helperMessage.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
helperMessage={{
password: "If not set, a password will be automatically generated.",
}}
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="password" label="Password">
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Displaying an Error Message
To display an error message, set a {[key: string]: ReactNode} to errorMessage.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Required
To make it required, set required to {[key: string]: boolean}.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Disable
To disable, set disabled to {[key: string]: boolean}.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
disabled={{ password: true }}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Read-Only
To make it read-only, set readOnly to {[key: string]: boolean}.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
description="Create an account to get started."
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
readOnly={{ password: true }}
submitButton="Submit"
title="Create an account"
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Customize Required Indicator
To customize the required indicator, set requiredIndicator to ReactNode.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
requiredIndicator={
<Tag colorScheme="red" size="sm">
required
</Tag>
}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)
Use Optional Indicator
To use an optional indicator, set a ReactNode to optionalIndicator.
const {
formState: { errors },
handleSubmit,
register,
} = useForm<Data>()
const onSubmit: SubmitHandler<Data> = (data) => console.log("submit:", data)
return (
<Form.Root
title="Create an account"
description="Create an account to get started."
submitButton="Submit"
errorMessage={extractObject(errors, (value) => value?.message)}
invalid={extractObject(errors, (value) => !!value)}
required={{ name: true, email: true }}
requiredIndicator={
<Tag colorScheme="red" size="sm">
required
</Tag>
}
optionalIndicator={
<Tag colorScheme="mono" size="sm">
optional
</Tag>
}
onSubmit={handleSubmit(onSubmit)}
>
<Form.Group>
<Field.Root name="name" label="Name">
<Input
placeholder="Hirotomo Yamada"
{...register("name", {
required: { message: "Name is required", value: true },
})}
/>
</Field.Root>
<Field.Root name="email" label="Email address">
<Input
placeholder="hirotomo@yamada-ui.com"
{...register("email", {
required: { message: "Email is required", value: true },
})}
/>
</Field.Root>
<Field.Root
name="password"
helperMessage="If not set, a password will be automatically generated."
label="Password"
>
<PasswordInput placeholder="password" {...register("password")} />
</Field.Root>
</Form.Group>
</Form.Root>
)