• English
  • Form

    Organize fields, labels and validation feedback, and collect form data.

    Submission and validation

    Live previewSubmission and validation
    Used for project notifications
    basic.tsx
    import { Button, Form, FormField, Input, Select } from '@sudden3/leaf-ui';
    import { useState } from 'react';
    export function FormBasic() {
      const [result, setResult] = useState('');
      return (
        <Form
          className="leaf-demo-stack leaf-demo-stack--wide"
          onSubmit={(event) => {
            event.preventDefault();
            const data = new FormData(event.currentTarget);
            setResult(`${data.get('name')} · ${data.get('email')} · ${data.get('team')}`);
          }}
          onReset={() => setResult('')}
        >
          <FormField label="Name" required>
            <Input name="name" placeholder="Your name" />
          </FormField>
          <FormField label="Work email" required help="Used for project notifications">
            <Input name="email" type="email" placeholder="hello@example.com" />
          </FormField>
          <FormField label="Team" required>
            <Select
              name="team"
              options={[
                { value: 'design', label: 'Design team' },
                { value: 'engineering', label: 'Engineering team' },
              ]}
            />
          </FormField>
          <FormField>
            <div className="leaf-demo-row">
              <Button type="submit">Submit</Button>
              <Button type="reset" variant="outline">
                Reset
              </Button>
            </div>
          </FormField>
          {result && <output className="leaf-demo-note">{result}</output>}
        </Form>
      );
    }
    

    Label widths

    Live previewLabel widths
    label-width.tsx
    import { Button, Form, FormField, Input, Switch } from '@sudden3/leaf-ui';
    import { useState } from 'react';
    export function FormLabelWidth() {
      const [automatic, setAutomatic] = useState(true);
      const [extra, setExtra] = useState(false);
      return (
        <div className="leaf-demo-stack leaf-demo-stack--wide">
          <div className="leaf-demo-row">
            <Switch checked={automatic} onChange={(event) => setAutomatic(event.target.checked)}>
              Automatic label widths
            </Switch>
            <Button variant="outline" onClick={() => setExtra(!extra)}>
              Toggle long label
            </Button>
          </div>
          <Form labelWidth={automatic ? 'auto' : 110}>
            <FormField label="Name">
              <Input name="name" />
            </FormField>
            <FormField label="Work email">
              <Input name="email" />
            </FormField>
            {extra && (
              <FormField label="Emergency contact number">
                <Input name="emergency" />
              </FormField>
            )}
          </Form>
        </div>
      );
    }
    

    Form API

    PropertyTypeDefaultDescription
    labelWidthnumber | 'auto''auto'A pixel width, or auto to align all labels to the widest label
    layout'horizontal' | 'vertical''horizontal'Label and field layout
    labelAlign'left' | 'right''right'Label alignment
    disabledbooleanfalseDisable Leaf controls inside the form
    onSubmit / onResetFormEventHandler<HTMLFormElement>—Standard submit / reset events
    refRef<HTMLFormElement>—Reference to the form

    FormField API

    PropertyTypeDefaultDescription
    label / help / errorReactNode—Label / help text / application error
    htmlForstringGeneratedThe associated control ID; one field wraps one control or group
    requiredbooleanfalseShow the required mark and pass required to the control
    labelWidthnumber—Override this field’s label width in pixels

    Types

    Import types when defining reusable component props or assembling options.

    import type { FormProps, FormFieldProps } from '@sudden3/leaf-ui';

    Usage notes

    By default, all labels in one Form use the width of its widest label. Widths update when text, fonts or mounted fields change. Vertical layouts and narrow screens stack labels above fields. Standard form attributes such as action, method, onSubmit and onReset are supported.

    Read named controls with FormData. Use required, type and minLength for basic validation; errors appear beside their fields. Pass application or server errors through error. Set noValidate when handling validation yourself. FormData contains strings, does not build nested objects, and omits unchecked checkboxes. Reset controlled fields in application state.