Form
Formは、複数のフォーム要素をグループ化するためのコンポーネントです。
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>
)
使い方
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>
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>
)
バリアントを変更する
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>
)
サイズを変更する
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>
)
ヘルプメッセージを表示する
ヘルプメッセージを表示する場合は、helperMessageに{[key: string]: 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"
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>
)
エラーメッセージを表示する
エラーメッセージを表示する場合は、errorMessageに{[key: string]: 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 }}
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に{[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>
)
無効にする
無効にする場合は、disabledに{[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>
)
読み取り専用にする
読み取り専用にする場合は、readOnlyに{[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>
)
必須インジケーターをカスタマイズする
必須インジケーターをカスタマイズする場合は、requiredIndicatorに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>
)
オプショナルインジケーターを使う
オプショナルインジケーターを使う場合は、optionalIndicatorに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>
}
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>
)
アクセシビリティ
ARIAロールと属性
| コンポーネント | ロールと属性 | 使い方 |
|---|---|---|
Form.Root | id | Form.SubmitButtonと関連付けるために使用するid。 |
aria-labelledby | 関連したForm.TitleとForm.Descriptionのidを設定します。 | |
Form.Title | id | Form.RootやForm.Descriptionと関連付けるために使用するid。 |
Form.Description | id | Form.Rootと関連付けるために使用するid。 |
aria-describedby | 関連したForm.Titleのidを設定します。 | |
Form.SubmitButton | form | 関連したForm.Rootのidを設定します。 |
Props
類似のコンポーネント
Field
Fieldは、フォーム要素に、ラベル、ヘルパーメッセージ、エラーメッセージなどをグループ化するために使用されるコンポーネントです。
Fieldset
Fieldsetは、フィールドセット要素に、レジェンド、ヘルパーメッセージ、エラーメッセージなどをグループ化するために使用されるコンポーネントです。
Bleed
Bleedは、要素をコンテナの境界から外すために使用されるコンポーネントです。
Box
Boxは、他のすべてのコンポーネントがその上に構築される最も抽象的なコンポーネントです。デフォルトでは、div要素をレンダリングします。
Center
Centerは、コンポーネント内の子要素を中央に配置するコンポーネントです。
Container
Containerは、汎用的な区分要素として使用するコンポーネントです。デフォルトでは、section要素をレンダリングします。
Flex
Flexは、Boxにflexを設定したコンポーネントです。また、便利なスタイルのショートハンドが用意されています。
Float
Floatは、要素をコンテナの端に固定するために使用されるコンポーネントです。