---
title: "FormSection"
description: "A form section with fieldset, legend and a one- or two-column grid. It groups related fields so reading and validation have a clear boundary."
kind: block
id: C-060
category: erp
registry: "form-section"
docs: "https://koten.codehive.com.co/blocks/erp/form-section"
markdown: "https://koten.codehive.com.co/md/blocks/erp/form-section.md"
install: "npx shadcn@latest add https://koten.codehive.com.co/r/form-section.json"
language: en
---

# FormSection · フォーム節

> Block C-060 in the Koten UI catalog.

A form section with fieldset, legend and a one- or two-column grid. It groups related fields so reading and validation have a clear boundary.

> Japanese labels in this page are documentation metadata. Keep the consumer UI in the product's language and do not add Japanese decoration unless the user asks (R-031).

## Install

Install `koten-theme` first when the project does not have Koten tokens yet. Use the runner of your project.

```bash
# Node
npx shadcn@latest add https://koten.codehive.com.co/r/form-section.json

# Bun
bunx shadcn@latest add https://koten.codehive.com.co/r/form-section.json
```

## Files

- `@/components/patterns/form-section.tsx`
- `@/lib/koten/cn.ts`
- `@/lib/koten/format.ts`
- `@/lib/koten/intl.ts`
- `@/lib/koten/labels.ts`
- `@/lib/koten/provider.tsx`

## Composition

This block composes Koten primitives. Read the source files above before changing its anatomy.

## Examples

### Complete form

Two-column section with required fields, a visible error, submit and an announced confirmation.

```tsx
<form
  noValidate
  onSubmit={saveCustomer}
  className="grid gap-[var(--koten-gap)]"
>
  <FormSection
    title="Customer"
    description="Contact and billing details"
    columns={2}
  >
    <Field label="Contact person" required>
      <Input placeholder="e.g. Taro Yamada" />
    </Field>
    <Field label="Email" required error="Enter a valid email address.">
      <Input type="email" defaultValue="taro@" />
    </Field>
    <Field label="Phone">
      <Input type="tel" placeholder="03-5550-0101" />
    </Field>
    <Select label="Channel" defaultValue="web" items={channelItems} />
  </FormSection>
  <div className="flex flex-wrap items-center justify-between gap-2">
    <p className="text-2xs text-muted">Fields marked * are required.</p>
    <Button type="submit" size="sm" variant="primary">
      Save customer
    </Button>
  </div>
</form>
```

### One column

columns={1} stacks the fields; useful in narrow panels.

```tsx
<FormSection
  title="Quick contact"
  description="Contact and billing details"
  columns={1}
  className="max-w-md"
>
  <Field label="Contact person" required>
    <Input placeholder="e.g. Taro Yamada" />
  </Field>
  <Field label="Email" required>
    <Input type="email" placeholder="taro@yamada.example" />
  </Field>
</FormSection>
```

## Props

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `title` | `ReactNode` | `—` | Legend content; it names the group of fields. |
| `description` | `ReactNode` | `—` | Help under the legend; it does not replace each field's label. |
| `children` | `ReactNode` | `—` | Field, Input, Select or labelled controls. |
| `columns` | `1 \| 2` | `2` | Two columns from 640 px; it always stacks on mobile. |
| `className` | `string` | `—` | Adds to the component's base classes. |

## Accessibility

- fieldset and legend group the fields; the legend is the group name, not a decorative title.
- columns only changes the grid: DOM order remains the reading and tab order.
- Errors come through Field (aria-invalid and aria-describedby); do not write them as loose text.
- The section submits nothing: the form, submit button and confirmation live outside.

## Sources

- Catalog page: https://koten.codehive.com.co/blocks/erp/form-section
- Markdown: https://koten.codehive.com.co/md/blocks/erp/form-section.md
- Repository: https://github.com/codehive-colombia/koten
