ChatGPT UI Form Control - Horizon AI Template

FormControl provides context such as isInvalid, isDisabled, and isRequired to form elements.

It follows the WAI specifications for forms.

Import#

import {
FormControl,
FormLabel,
FormErrorMessage,
FormHelperText,
} from "@chakra-ui/react"

Usage#

<FormControl id="email">
<FormLabel>Email address</FormLabel>
<Input type="email" borderRadius="16px" />
<FormHelperText>We'll never share your email.</FormHelperText>
</FormControl>
<FormControl id="email">
<FormLabel>Email address</FormLabel>
<Input type="email" />
<FormHelperText>We'll never share your email.</FormHelperText>
</FormControl>

Sample usage for a radio or checkbox group#

<FormControl as="fieldset">
<FormLabel as="legend">Favorite Naruto Character</FormLabel>
<RadioGroup defaultValue="Itachi">
<HStack spacing="24px">
<Radio value="Sasuke">Sasuke</Radio>
<Radio value="Nagato">Nagato</Radio>
<Radio value="Itachi">Itachi</Radio>
<Radio value="Sage of the six Paths">Sage of the six Paths</Radio>
</HStack>
</RadioGroup>
<FormHelperText>Select only if you're a fan.</FormHelperText>
</FormControl>
<FormControl as="fieldset">
<FormLabel as="legend">Favorite Naruto Character</FormLabel>
<RadioGroup defaultValue="Itachi">
<HStack spacing="24px">
<Radio value="Sasuke">Sasuke</Radio>
<Radio value="Nagato">Nagato</Radio>
<Radio value="Itachi">Itachi</Radio>
<Radio value="Sage of the six Paths">Sage of the six Paths</Radio>
</HStack>
</RadioGroup>
<FormHelperText>Select only if you're a fan.</FormHelperText>
</FormControl>

Making a field required#

By passing the isRequired props, the Input field has aria-required set to true, and the FormLabel will show a red asterisk.

<FormControl id="first-name" isRequired>
<FormLabel>First name</FormLabel>
<Input placeholder="First name" borderRadius="16px" />
</FormControl>
<FormControl id="first-name" isRequired>
<FormLabel>First name</FormLabel>
<Input placeholder="First name" borderRadius="16px" />
</FormControl>

Select Example#

<FormControl id="country">
<FormLabel>Country</FormLabel>
<Select placeholder="Select country">
<option>Romania</option>
</Select>
</FormControl>
<FormControl id="country">
<FormLabel>Country</FormLabel>
<Select placeholder="Select country">
<option>Romania</option>
</Select>
</FormControl>

Number Input Example#

<FormControl id="amount">
<FormLabel>Amount</FormLabel>
<NumberInput max={50} min={10}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</FormControl>
<FormControl id="amount">
<FormLabel>Amount</FormLabel>
<NumberInput max={50} min={10}>
<NumberInputField />
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
</FormControl>

Usage with Form Libraries#

Form Libraries like Formik make it soooo easy to manage form state and validation. I 💖 Formik

function FormikExample() {
function validateName(value) {
let error
if (!value) {
error = "Name is required"
} else if (value.toLowerCase() !== "naruto") {
error = "Jeez! You're not a fan 😱"
}
return error
}
return (
<Formik
initialValues={{ name: "Sasuke" }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
>
{(props) => (
<Form>
<Field name="name" validate={validateName}>
{({ field, form }) => (
<FormControl isInvalid={form.errors.name && form.touched.name}>
<FormLabel htmlFor="name">First name</FormLabel>
<Input
{...field}
id="name"
placeholder="name"
borderRadius="16px"
/>
<FormErrorMessage>{form.errors.name}</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme="brand"
isLoading={props.isSubmitting}
type="submit"
>
Submit
</Button>
</Form>
)}
</Formik>
)
}
function FormikExample() {
function validateName(value) {
let error
if (!value) {
error = "Name is required"
} else if (value.toLowerCase() !== "naruto") {
error = "Jeez! You're not a fan 😱"
}
return error
}
return (
<Formik
initialValues={{ name: "Sasuke" }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
>
{(props) => (
<Form>
<Field name="name" validate={validateName}>
{({ field, form }) => (
<FormControl isInvalid={form.errors.name && form.touched.name}>
<FormLabel htmlFor="name">First name</FormLabel>
<Input
{...field}
id="name"
placeholder="name"
borderRadius="16px"
/>
<FormErrorMessage>{form.errors.name}</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme="brand"
isLoading={props.isSubmitting}
type="submit"
>
Submit
</Button>
</Form>
)}
</Formik>
)
}

Improvements from v1#

  • We've improved the accessibility of the FormControl component. Here are the changes:

    • id passed to the form control will be passed to the form input directly.
    • FormLabel will have htmlFor that points to the id of the form input.
    • FormErrorMessage adds aria-describedby and aria-invalid pointing to the form input.
    • FormHelperText adds/extends aria-describedby pointing to the form input.
    • isDisabled, isRequired, isReadOnly props passed to FormControl will cascade across all related components.
  • FormLabel is now aware of the disabled, focused and error state of the form input. This helps you style the label accordingly using the _disabled, _focus, and _invalid style props.

  • If you render FormErrorMessage and isInvalid is false or undefined, FormErrorMessage won't be visible. The only way to make it visible is by passing isInvalid and setting it to true.

Props#

colorScheme

Description

Color Schemes for FormControl are not implemented in the default theme. You can extend the themeto implement them.

Type
"brand" | "whiteAlpha" | "blackAlpha" | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink" | "linkedin" | "facebook" | ... 4 more ...

isDisabled

Description

If true, the form control will be disabled. This has 2 side effects: - The FormLabel will have `data-disabled` attribute - The form element (e.g, Input) will be disabled

Type
boolean

isInvalid

Description

If true, the form control will be invalid. This has 2 side effects: - The FormLabel and FormErrorIcon will have `data-invalid` set to true - The form element (e.g, Input) will have `aria-invalid` set to true

Type
boolean

isReadOnly

Description

If true, the form control will be readonly

Type
boolean

isRequired

Description

If true, the form control will be required. This has 2 side effects: - The FormLabel will show a required indicator - The form element (e.g, Input) will have `aria-required` set to true

Type
boolean

label

Description

The label text used to inform users as to what information is requested for a text field.

Type
string

size

Type
string

variant

Type
string

Horizon AI Template © 2021-2023 Copyright. All Rights Reserved.

  • Blog
  • License