Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Grid Layout (2 Columns) Form for Ark UI

Six contact fields in two columns: first and last name, email and phone, then city and ZIP code.

First and last name share a row, then email and phone, then city and ZIP. Phone needs 10 characters. ZIP is a 5-digit or ZIP+4 code. Submit checks all six.

Use it when pairs belong side by side and height matters. One column is the ordinary stacked Field. In React, Ark UI does not set the two columns. The grid does.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Usage

<form className="w-full max-w-2xl" onSubmit={form.handleSubmit(onSubmit)}>
  <FieldGroup>
    <div className="grid grid-cols-2 gap-4">
      {fields.map((item) => (
        <Controller
          control={form.control}
          key={item.name}
          name={item.name}
          render={({ field, fieldState }) => (
            <Field invalid={fieldState.invalid}>
              <FieldLabel>{item.label}</FieldLabel>
              <Input
                {...field}
                placeholder={item.placeholder}
                type={item.type}
              />
              <FieldError>{fieldState.error?.message}</FieldError>
            </Field>
          )}
        />
      ))}
    </div>
    <Field orientation="horizontal">
      <Button type="submit">Submit</Button>
    </Field>
  </FieldGroup>
</form>

FAQ

How are the pairs arranged?

One div with grid grid-cols-2 gap-4 holds all six fields in order, so they fill three rows of two. The form is max-w-2xl, and Submit sits under the grid in a horizontal Field.

What does each field check, and where is the message?

firstName, lastName and city are z.string().min(2), email is z.email(), phone is z.string().min(10) and zipCode is z.string().regex(ZIP_CODE_PATTERN). None passes a custom message, so each FieldError shows Zod's default under its input.

Which ZIP values match?

ZIP_CODE_PATTERN is /^\d{5}(-\d{4})?$/: five digits, optionally followed by a hyphen and four more, such as 10001 or 10001-0000. The placeholder is 10001.

Which inputs set a type?

The six fields come from one fields array mapped to a Controller each, with a label, name, placeholder and type. Email is type="email", phone is type="tel" and the rest are text.

What are the initial values?

defaultValues sets city, email, firstName, lastName, phone and zipCode to empty strings.

When does the grid validate?

useForm doesn't set mode, so form.handleSubmit(onSubmit) checks every field on submit and logs the values once all six pass.

API Reference

Field

Sets invalid={fieldState.invalid} and orientation="horizontal". The rest is on the Field page.

Input

Sets field, placeholder={item.placeholder} and type={item.type}. The rest is on the Input page.

Button

Sets type="submit". The rest is on the Button page.