Skip to content

Form

Stacks fields with even spacing and leaves validation to the app: fields show its messages, never the browser bubbles. validationErrors shows a server answer under each field; FormError says why the whole form was not saved.

Language
Appearance

A new contact

Save with the name empty, then with “taken@example.com” as the email.

Preferred channel
import { useState } from 'react';
import { Button, Checkbox, Form, FormError, Select, SelectItem, TextField } from '@arbol-ai/ui';

const NewContactExample = () => {
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [refusal, setRefusal] = useState<string>();
  return (
    <Form
      className="max-w-sm"
      onSubmit={(event) => {
        event.preventDefault();
        const data = new FormData(event.currentTarget);
        const name = data.get('name');
        setErrors(typeof name === 'string' && name.trim() !== '' ? {} : { name: 'Enter the contact name.' });
        setRefusal(
          data.get('email') === 'taken@example.com'
            ? 'A contact with that email already exists. Open it instead of creating another.'
            : undefined
        );
      }}
      validationErrors={errors}
    >
      <TextField isRequired label="Name" name="name" />
      <TextField label="Email" name="email" type="email" />
      <Select defaultValue="whatsapp" label="Preferred channel" name="channel">
        <SelectItem id="whatsapp">WhatsApp</SelectItem>
        <SelectItem id="voice">Phone call</SelectItem>
      </Select>
      <Checkbox defaultSelected name="reminders">
        Send appointment reminders
      </Checkbox>
      <FormError>{refusal}</FormError>
      <Button className="self-start" type="submit">
        Save contact
      </Button>
    </Form>
  );
};

<NewContactExample />

Source

The examples above are src/components/form/form.examples.tsx, which the library’s tests render too.

Type to search…

↑↓ navigate↵ selectEsc close