How to build a form using Marigold components?

main
d73b335chore: add react and nextjs custom agents (#5037)

How to build a form using components from Marigold?

Avatar of Claude Haiku 4.5Claude Haiku 4.5commented

I'll help you understand how to build a form using components from Marigold. Let me explore the repository structure first to find form-related components and documentation.

Great! I can see there's comprehensive documentation about forms. Let me look at the Form implementation guide and form components:

Now let me check what form components are available:

Let me also look at some practical examples in the codebase:

Let me find the actual demo files:

Perfect! Let me check a few practical examples:

Perfect! Now let me get one more example with validation:

Excellent! Now I have enough information to provide a comprehensive answer. Let me create a detailed summary:

##How to Build a Form Using Marigold Components

Here's a comprehensive guide based on the Marigold documentation:

###Basic Form Structure

Marigold provides a <Form> component that acts as a container for your form fields. Here's the simplest approach:

import { Form, TextField, Button, Stack } from '@marigold/components';

export default function MyForm() {
  return (
    <Form onSubmit={(e) => {
      e.preventDefault();
      const formData = new FormData(e.currentTarget);
      const data = Object.fromEntries(formData);
      console.log(data);
    }}>
      <Stack space={4}>
        <TextField name="email" label="Email" />
        <TextField name="password" label="Password" type="password" />
        <Button type="submit">Submit</Button>
      </Stack>
    </Form>
  );
}

###Available Form Components

Marigold offers a full suite of form components:

  • Text Input: TextField, TextArea, SearchField
  • Selection: Select, Checkbox, Radio, Switch
  • Multi-Selection: Multiselect, Autocomplete, Combobox
  • Numbers & Dates: NumberField, DateField, DatePicker, TimeField, Calendar, Slider
  • File Input: FileField
  • Container: Form, Label

###Using Uncontrolled Components (Simple Forms)

For simple forms without complex validation, use uncontrolled components with the browser's FormData API:

const [state, formAction] = useActionState<FormState, FormData>(
  (_previousState: FormState, formData: FormData) => {
    return { promoCode: formData.get('promocode') };
  },
  INITIAL_STATE
);

return (
  <Form action={formAction}>
    <Stack space={1} alignX="left">
      <TextField label="Promo Code" name="promocode" width={44} />
      <Button variant="primary" size="small" type="submit">
        Submit
      </Button>
    </Stack>
  </Form>
);

###Form Field Anatomy

Each form field should include:

  1. Label: Describes what the user should enter
  2. Input Control: The actual input element
  3. Description (optional): Helper text providing additional context
  4. Error Message (optional): Displayed when validation fails
<TextField
  name="email"
  label="Email Address"
  description="We'll never share your email"
  error={hasError}
  errorMessage="Please enter a valid email"
  required
/>

###Validation Approaches

####1. With React Hook Form (Recommended for Complex Forms)

import { Controller, useForm } from 'react-hook-form';

export default function ComplexForm() {
  const { control, handleSubmit, formState: { isValid } } = useForm({
    mode: 'onChange',
    defaultValues: {
      firstName: '',
      email: '',
    },
  });

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <Stack space={4}>
        <Controller
          name="firstName"
          control={control}
          rules={{ required: 'First name is required' }}
          render={({ field, fieldState: { error } }) => (
            <TextField
              {...field}
              label="First Name"
              required
              error={!!error}
              errorMessage={error?.message}
            />
          )}
        />
        <Button type="submit" disabled={!isValid}>Submit</Button>
      </Stack>
    </form>
  );
}

####2. With Zod Schema Validation

import { z } from 'zod';

export default function FormWithZod() {
  const schema = z.object({
    email: z.string().email('Invalid email'),
    name: z.string().min(1, 'Name required'),
  });

  const [errors, setErrors] = useState<string[]>([]);

  const handleSubmit: FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const data = Object.fromEntries(formData);
    
    const validation = schema.safeParse(data);
    if (!validation.success) {
      setErrors(validation.error.issues.map(issue => issue.path.toString()));
    } else {
      // Submit form
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <TextField
        name="email"
        label="Email"
        error={errors.includes('email')}
        errorMessage="Invalid email"
      />
      <Button type="submit">Submit</Button>
    </form>
  );
}

###Error Handling

The <Form> component automatically handles validation errors from servers:

<Form validationErrors={serverErrors}>
  <TextField name="email" label="Email" />
</Form>

When validationErrors is set, errors appear below fields and are automatically cleared when users modify the field.

###Layout Components for Forms

Use layout components to structure your forms:

<Stack space={4}>           {/* Vertical stacking */}
  <Columns columns={[2]}>   {/* 2-column grid */}
    <TextField label="First Name" />
    <TextField label="Last Name" />
  </Columns>
  <Inset>                   {/* Add spacing around content */}
    <TextField label="Email" />
  </Inset>
</Stack>

###Key Takeaways

  1. Always include a name attribute on form fields for data submission
  2. Use labels for accessibility and clarity
  3. Choose controlled (React Hook Form) or uncontrolled approaches based on complexity
  4. Validate early and often with clear error messages
  5. Test accessibility with screen readers and keyboard navigation
  6. Use layout components like Stack, Columns, and Inset for consistent spacing

For more detailed examples and patterns, check the Form Implementation Guide and Form Fields documentation in the Marigold docs.


END OF POST

Log in to add a comment
Claude Haiku 4.5
How to build a form using Marigold components? — marigold-ui/marigold