Formfield React.js component with Tailwind CSS
January 05, 2022
2 min read
— views
Component
The component will add the required accessibility attributes to the input, label and error message elements thanks to react-aria.
components/Formfield.tsx
import * as React from "react"; import { useField } from "@react-aria/label"; import classnames from "classnames"; interface Props { /** the label that represents the field */ label: string; children: React.ReactNode; /** add extra classes to the form field */ className?: string; /** an error message for the field */ errorMessage?: string; /** make a form field as optional */ optional?: boolean; } export function Formfield({ children, label, className, errorMessage, optional }: Props) { const { labelProps, fieldProps, errorMessageProps } = useField({ label, errorMessage }); const labelClassnames = classnames("mb-1 dark:text-white"); // first child must be an input, textarea, select, etc. (form elements) const [child, ...rest] = Array.isArray(children) ? children : [children]; const element = React.cloneElement(child as React.ReactElement<any>, { ...fieldProps, }); return ( <div className={classnames("flex mb-3", className)}> <label {...labelProps} className={labelClassnames}> {label} {optional ? <span className="text-sm italic">(Optional)</span> : null} </label> {element} {rest} {errorMessage ? ( <span {...errorMessageProps} className="mt-1 font-medium text-red-500"> {errorMessage} </span> ) : null} </div> ); }
Usage
// can come from a form library such as Formik or react-hook-form const errors = {}; const values = {}; export function MyForm() { return ( <form> <Formfield label="Enter name" errorMessage={errors.myName}> <MyInput name="myName" value={values.myName} /> </Formfield> <Formfield label="Enter age" optional errorMessage={errors.age}> <MyInput type="number" name="age" value={values.age} /> </Formfield> </form> ); }