---
title: Field
description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
---

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/checkbox"
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/input"
	selectcomp "github.com/axadrn/shadcn-templ/v2/components/select"
	"github.com/axadrn/shadcn-templ/v2/components/textarea"
)

templ FieldDemo() {
	<div class="w-full max-w-md">
		<form>
			@field.Group() {
				@field.Set() {
					@field.Legend() {
						Payment Method
					}
					@field.Description() {
						All transactions are secure and encrypted
					}
					@field.Group() {
						@field.Field() {
							@field.Label(field.LabelProps{For: "checkout-7j9-card-name-43j"}) {
								Name on Card
							}
							@input.Input(input.Props{
								ID:          "checkout-7j9-card-name-43j",
								Placeholder: "Axel Adrian",
							})
						}
						@field.Field() {
							@field.Label(field.LabelProps{For: "checkout-7j9-card-number-uw1"}) {
								Card Number
							}
							@input.Input(input.Props{
								ID:          "checkout-7j9-card-number-uw1",
								Placeholder: "1234 5678 9012 3456",
							})
							@field.Description() {
								Enter your 16-digit card number
							}
						}
						<div class="grid grid-cols-3 gap-4">
							@field.Field() {
								@field.Label(field.LabelProps{For: "checkout-exp-month-ts6"}) {
									Month
								}
								@selectcomp.Select() {
									@selectcomp.Trigger(selectcomp.TriggerProps{ID: "checkout-exp-month-ts6"}) {
										@selectcomp.Value(selectcomp.ValueProps{Placeholder: "MM"})
									}
									@selectcomp.Content() {
										@selectcomp.Item(selectcomp.ItemProps{Value: "01"}) {
											01
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "02"}) {
											02
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "03"}) {
											03
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "04"}) {
											04
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "05"}) {
											05
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "06"}) {
											06
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "07"}) {
											07
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "08"}) {
											08
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "09"}) {
											09
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "10"}) {
											10
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "11"}) {
											11
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "12"}) {
											12
										}
									}
								}
							}
							@field.Field() {
								@field.Label(field.LabelProps{For: "checkout-7j9-exp-year-f59"}) {
									Year
								}
								@selectcomp.Select() {
									@selectcomp.Trigger(selectcomp.TriggerProps{ID: "checkout-7j9-exp-year-f59"}) {
										@selectcomp.Value(selectcomp.ValueProps{Placeholder: "YYYY"})
									}
									@selectcomp.Content() {
										@selectcomp.Item(selectcomp.ItemProps{Value: "2024"}) {
											2024
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "2025"}) {
											2025
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "2026"}) {
											2026
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "2027"}) {
											2027
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "2028"}) {
											2028
										}
										@selectcomp.Item(selectcomp.ItemProps{Value: "2029"}) {
											2029
										}
									}
								}
							}
							@field.Field() {
								@field.Label(field.LabelProps{For: "checkout-7j9-cvv"}) {
									CVV
								}
								@input.Input(input.Props{
									ID:          "checkout-7j9-cvv",
									Placeholder: "123",
								})
							}
						</div>
					}
				}
				@field.Separator()
				@field.Set() {
					@field.Legend() {
						Billing Address
					}
					@field.Description() {
						The billing address associated with your payment method
					}
					@field.Group() {
						@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
							@checkbox.Checkbox(checkbox.Props{
								ID:      "checkout-7j9-same-as-shipping-wgm",
								Checked: true,
							})
							@field.Label(field.LabelProps{
								For:   "checkout-7j9-same-as-shipping-wgm",
								Class: "font-normal",
							}) {
								Same as shipping address
							}
						}
					}
				}
				@field.Set() {
					@field.Group() {
						@field.Field() {
							@field.Label(field.LabelProps{For: "checkout-7j9-optional-comments"}) {
								Comments
							}
							@textarea.Textarea(textarea.Props{
								ID:          "checkout-7j9-optional-comments",
								Placeholder: "Add any additional comments",
								Class:       "resize-none",
							})
						}
					}
				}
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@button.Button(button.Props{Type: button.TypeSubmit}) {
						Submit
					}
					@button.Button(button.Props{
						Variant: button.VariantOutline,
						Type:    button.TypeButton,
					}) {
						Cancel
					}
				}
			}
		</form>
	</div>
}
```

## Installation

<CodeTabs>

<TabsList>
  <TabsTrigger value="cli">Command</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
shadcn-templ add field
```

</TabsContent>

<TabsContent value="manual">

<Steps className="mb-0 pt-2">

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="field" title="components/field/field.templ" />

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</CodeTabs>

## Usage

```go showLineNumbers
import "github.com/axadrn/shadcn-templ/v2/components/field"
```

```templ showLineNumbers
@field.Set() {
	@field.Legend() {
		Profile
	}
	@field.Description() {
		This appears on invoices and emails.
	}
	@field.Group() {
		@field.Field() {
			@field.Label(field.LabelProps{For: "name"}) {
				Full name
			}
			@input.Input(input.Props{ID: "name", Placeholder: "Axel Adrian"})
			@field.Description() {
				This appears on invoices and emails.
			}
		}
		@field.Field() {
			@field.Label(field.LabelProps{For: "username"}) {
				Username
			}
			@input.Input(input.Props{ID: "username", Attributes: templ.Attributes{"aria-invalid": "true"}})
			@field.Error() {
				Choose another username.
			}
		}
		@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
			@switchcomp.Switch(switchcomp.Props{ID: "newsletter"})
			@field.Label(field.LabelProps{For: "newsletter"}) {
				Subscribe to the newsletter
			}
		}
	}
}
```

## Composition

### Field

A single control with label, helper text, and validation.

```text
field.Field
├── field.Label
├── input.Input / textarea.Textarea / switchcomp.Switch / select.Select
├── field.Description
└── field.Error
```

### FieldGroup

Related fields in one group. Use `field.Separator` between sections when needed.

```text
field.Group
├── field.Field
│   ├── field.Label
│   ├── input.Input / textarea.Textarea / switchcomp.Switch / select.Select
│   ├── field.Description
│   └── field.Error
├── field.Separator
└── field.Field
    ├── field.Label
    └── input.Input / textarea.Textarea / switchcomp.Switch / select.Select
```

### FieldSet

Semantic grouping with a legend and description, usually containing a `field.Group`.

```text
field.Set
├── field.Legend
├── field.Description
└── field.Group
    ├── field.Field
    │   ├── field.Label
    │   ├── input.Input / textarea.Textarea / switchcomp.Switch / select.Select
    │   ├── field.Description
    │   └── field.Error
    └── field.Field
        ├── field.Label
        └── input.Input / textarea.Textarea / switchcomp.Switch / select.Select
```

## Anatomy

The `Field` family is designed for composing accessible forms. A typical field is structured as follows:

```templ showLineNumbers
@field.Field() {
	@field.Label(field.LabelProps{For: "input-id"}) {
		Label
	}
	// Input, Select, Switch, etc.
	@field.Description() {
		Optional helper text.
	}
	@field.Error() {
		Validation message.
	}
}
```

- `Field` is the core wrapper for a single field.
- `field.Content` is a flex column that groups label and description. Not required if you have no description.
- Wrap related fields with `field.Group`, and use `field.Set` with `field.Legend` for semantic grouping.

## Form

Fields compose with plain HTML forms, the controls submit their native values.

## Input

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/input"
)

templ FieldInput() {
	@field.Set(field.SetProps{Class: "w-full max-w-xs"}) {
		@field.Group() {
			@field.Field() {
				@field.Label(field.LabelProps{For: "username"}) {
					Username
				}
				@input.Input(input.Props{
					ID:          "username",
					Type:        "text",
					Placeholder: "axadrn",
				})
				@field.Description() {
					Choose a unique username for your account.
				}
			}
			@field.Field() {
				@field.Label(field.LabelProps{For: "password"}) {
					Password
				}
				@field.Description() {
					Must be at least 8 characters long.
				}
				@input.Input(input.Props{
					ID:          "password",
					Type:        "password",
					Placeholder: "••••••••",
				})
			}
		}
	}
}
```

## Textarea

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/textarea"
)

templ FieldTextarea() {
	@field.Set(field.SetProps{Class: "w-full max-w-xs"}) {
		@field.Group() {
			@field.Field() {
				@field.Label(field.LabelProps{For: "feedback"}) {
					Feedback
				}
				@textarea.Textarea(textarea.Props{
					ID:          "feedback",
					Placeholder: "Your feedback helps us improve...",
					Rows:        4,
				})
				@field.Description() {
					Share your thoughts about our service.
				}
			}
		}
	}
}
```

## Select

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	selectcomp "github.com/axadrn/shadcn-templ/v2/components/select"
)

templ FieldSelect() {
	@field.Field(field.Props{Class: "w-full max-w-xs"}) {
		@field.Label() {
			Department
		}
		@selectcomp.Select() {
			@selectcomp.Trigger() {
				@selectcomp.Value(selectcomp.ValueProps{Placeholder: "Choose department"})
			}
			@selectcomp.Content() {
				@selectcomp.Item(selectcomp.ItemProps{Value: "engineering"}) {
					Engineering
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "design"}) {
					Design
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "marketing"}) {
					Marketing
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "sales"}) {
					Sales
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "support"}) {
					Customer Support
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "hr"}) {
					Human Resources
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "finance"}) {
					Finance
				}
				@selectcomp.Item(selectcomp.ItemProps{Value: "operations"}) {
					Operations
				}
			}
		}
		@field.Description() {
			Select your department or area of work.
		}
	}
}
```

## Slider

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/slider"
)

templ FieldSlider() {
	@field.Field(field.Props{Class: "w-full max-w-xs"}) {
		@field.Title() {
			Price Range
		}
		@field.Description() {
			Set your budget range ($<span id="field-slider-min" class="font-medium tabular-nums">200</span> - <span id="field-slider-max" class="font-medium tabular-nums">800</span>).
		}
		@slider.Slider(slider.Props{
			ID:     "field-slider",
			Value: []float64{200, 800},
			Min:    0,
			Max:    1000,
			Step:   10,
			Class:  "mt-2 w-full",
			Attributes: templ.Attributes{
				"aria-label": "Price Range",
			},
		})
	}
	<script>
		// The vanilla pendant of the demo's React state.
		(() => {
			const root = document.getElementById("field-slider");
			root.addEventListener("slider-change", (e) => {
				document.getElementById("field-slider-min").textContent = e.detail.values[0];
				document.getElementById("field-slider-max").textContent = e.detail.values[1];
			});
		})();
	</script>
}
```

## Fieldset

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/input"
)

templ FieldFieldset() {
	@field.Set(field.SetProps{Class: "w-full max-w-sm"}) {
		@field.Legend() {
			Address Information
		}
		@field.Description() {
			We need your address to deliver your order.
		}
		@field.Group() {
			@field.Field() {
				@field.Label(field.LabelProps{For: "street"}) {
					Street Address
				}
				@input.Input(input.Props{
					ID:          "street",
					Type:        "text",
					Placeholder: "123 Main St",
				})
			}
			<div class="grid grid-cols-2 gap-4">
				@field.Field() {
					@field.Label(field.LabelProps{For: "city"}) {
						City
					}
					@input.Input(input.Props{
						ID:          "city",
						Type:        "text",
						Placeholder: "New York",
					})
				}
				@field.Field() {
					@field.Label(field.LabelProps{For: "zip"}) {
						Postal Code
					}
					@input.Input(input.Props{
						ID:          "zip",
						Type:        "text",
						Placeholder: "90502",
					})
				}
			</div>
		}
	}
}
```

## Checkbox

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/checkbox"
	"github.com/axadrn/shadcn-templ/v2/components/field"
)

templ FieldCheckbox() {
	@field.Group(field.GroupProps{Class: "w-full max-w-xs"}) {
		@field.Set() {
			@field.Legend(field.LegendProps{Variant: field.LegendVariantLabel}) {
				Show these items on the desktop
			}
			@field.Description() {
				Select the items you want to show on the desktop.
			}
			@field.Group(field.GroupProps{Class: "gap-3"}) {
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "finder-pref-9k2-hard-disks-ljj"})
					@field.Label(field.LabelProps{
						For:   "finder-pref-9k2-hard-disks-ljj",
						Class: "font-normal",
					}) {
						Hard disks
					}
				}
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "finder-pref-9k2-external-disks-1yg"})
					@field.Label(field.LabelProps{
						For:   "finder-pref-9k2-external-disks-1yg",
						Class: "font-normal",
					}) {
						External disks
					}
				}
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "finder-pref-9k2-cds-dvds-fzt"})
					@field.Label(field.LabelProps{
						For:   "finder-pref-9k2-cds-dvds-fzt",
						Class: "font-normal",
					}) {
						CDs, DVDs, and iPods
					}
				}
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "finder-pref-9k2-connected-servers-6l2"})
					@field.Label(field.LabelProps{
						For:   "finder-pref-9k2-connected-servers-6l2",
						Class: "font-normal",
					}) {
						Connected servers
					}
				}
			}
		}
		@field.Separator()
		@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
			@checkbox.Checkbox(checkbox.Props{
				ID:      "finder-pref-9k2-sync-folders-nep",
				Checked: true,
			})
			@field.Content() {
				@field.Label(field.LabelProps{For: "finder-pref-9k2-sync-folders-nep"}) {
					Sync Desktop & Documents folders
				}
				@field.Description() {
					Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.
				}
			}
		}
	}
}
```

## Radio

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/radiogroup"
)

templ FieldRadio() {
	@field.Set(field.SetProps{Class: "w-full max-w-xs"}) {
		@field.Legend(field.LegendProps{Variant: field.LegendVariantLabel}) {
			Subscription Plan
		}
		@field.Description() {
			Yearly and lifetime plans offer significant savings.
		}
		<div data-slot="radio-group" class="grid gap-3">
			@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
				@radiogroup.Item(radiogroup.ItemProps{
					Name:    "plan",
					Value:   "monthly",
					ID:      "plan-monthly",
					Checked: true,
				})
				@field.Label(field.LabelProps{
					For:   "plan-monthly",
					Class: "font-normal",
				}) {
					Monthly ($9.99/month)
				}
			}
			@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
				@radiogroup.Item(radiogroup.ItemProps{
					Name:  "plan",
					Value: "yearly",
					ID:    "plan-yearly",
				})
				@field.Label(field.LabelProps{
					For:   "plan-yearly",
					Class: "font-normal",
				}) {
					Yearly ($99.99/year)
				}
			}
			@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
				@radiogroup.Item(radiogroup.ItemProps{
					Name:  "plan",
					Value: "lifetime",
					ID:    "plan-lifetime",
				})
				@field.Label(field.LabelProps{
					For:   "plan-lifetime",
					Class: "font-normal",
				}) {
					Lifetime ($299.99)
				}
			}
		</div>
	}
}
```

## Switch

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	switchcomp "github.com/axadrn/shadcn-templ/v2/components/switch"
)

templ FieldSwitch() {
	@field.Field(field.Props{
		Orientation: field.OrientationHorizontal,
		Class:       "w-fit",
	}) {
		@field.Label(field.LabelProps{For: "2fa"}) {
			Multi-factor authentication
		}
		@switchcomp.Switch(switchcomp.Props{ID: "2fa"})
	}
}
```

## Choice Card

Wrap `field.Field` components inside `field.Label` to create selectable field groups. This works with `radio.Radio`, `checkbox.Checkbox` and `switchcomp.Switch` components.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/radiogroup"
)

templ FieldChoiceCard() {
	@field.Group(field.GroupProps{Class: "w-full max-w-xs"}) {
		@field.Set() {
			@field.Legend(field.LegendProps{Variant: field.LegendVariantLabel}) {
				Compute Environment
			}
			@field.Description() {
				Select the compute environment for your cluster.
			}
			<div data-slot="radio-group" class="grid gap-3">
				@field.Label(field.LabelProps{For: "kubernetes-r2h"}) {
					@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
						@field.Content() {
							@field.Title() {
								Kubernetes
							}
							@field.Description() {
								Run GPU workloads on a K8s cluster.
							}
						}
						@radiogroup.Item(radiogroup.ItemProps{
							Name:    "compute",
							Value:   "kubernetes",
							ID:      "kubernetes-r2h",
							Checked: true,
						})
					}
				}
				@field.Label(field.LabelProps{For: "vm-z4k"}) {
					@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
						@field.Content() {
							@field.Title() {
								Virtual Machine
							}
							@field.Description() {
								Access a cluster to run GPU workloads.
							}
						}
						@radiogroup.Item(radiogroup.ItemProps{
							Name:  "compute",
							Value: "vm",
							ID:    "vm-z4k",
						})
					}
				}
			</div>
		}
	}
}
```

## Field Group

Stack `field.Field` components with `field.Group`. Add `field.Separator` to divide them.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/checkbox"
	"github.com/axadrn/shadcn-templ/v2/components/field"
)

templ FieldGroupExample() {
	@field.Group(field.GroupProps{Class: "w-full max-w-xs"}) {
		@field.Set() {
			@field.Label() {
				Responses
			}
			@field.Description() {
				Get notified when ChatGPT responds to requests that take time, like research or image generation.
			}
			@field.Group(field.GroupProps{Attributes: templ.Attributes{"data-slot": "checkbox-group"}}) {
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{
						ID:       "push",
						Checked:  true,
						Disabled: true,
					})
					@field.Label(field.LabelProps{
						For:   "push",
						Class: "font-normal",
					}) {
						Push notifications
					}
				}
			}
		}
		@field.Separator()
		@field.Set() {
			@field.Label() {
				Tasks
			}
			@field.Description() {
				Get notified when tasks you've created have updates.
				<a href="#">Manage tasks</a>
			}
			@field.Group(field.GroupProps{Attributes: templ.Attributes{"data-slot": "checkbox-group"}}) {
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "push-tasks"})
					@field.Label(field.LabelProps{
						For:   "push-tasks",
						Class: "font-normal",
					}) {
						Push notifications
					}
				}
				@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
					@checkbox.Checkbox(checkbox.Props{ID: "email-tasks"})
					@field.Label(field.LabelProps{
						For:   "email-tasks",
						Class: "font-normal",
					}) {
						Email notifications
					}
				}
			}
		}
	}
}
```

## Responsive Layout

- **Vertical fields:** Default orientation stacks label, control, and helper text—ideal for mobile-first layouts.
- **Horizontal fields:** Set `Orientation: field.OrientationHorizontal` on `field.Field` to align the label and control side-by-side. Pair with `field.Content` to keep descriptions aligned.
- **Responsive fields:** Set `Orientation: field.OrientationResponsive` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `field.Group` to switch orientations at specific breakpoints.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/input"
)

templ FieldResponsive() {
	<div class="w-full max-w-lg">
		<form>
			@field.Set() {
				@field.Legend() {
					Profile
				}
				@field.Description() {
					Fill in your profile information.
				}
				@field.Group() {
					@field.Field(field.Props{Orientation: field.OrientationResponsive}) {
						@field.Content() {
							@field.Label(field.LabelProps{For: "name"}) {
								Name
							}
							@field.Description() {
								Provide your full name for identification
							}
						}
						@input.Input(input.Props{
							ID:          "name",
							Placeholder: "Axel Adrian",
						})
					}
					@field.Field(field.Props{Orientation: field.OrientationResponsive}) {
						@button.Button(button.Props{Type: button.TypeSubmit}) {
							Submit
						}
						@button.Button(button.Props{
							Type:    button.TypeButton,
							Variant: button.VariantOutline,
						}) {
							Cancel
						}
					}
				}
			}
		</form>
	</div>
}
```

## Validation and Errors

- Add `data-invalid` to `field.Field` to switch the entire block into an error state.
- Add `aria-invalid` on the input itself for assistive technologies.
- Render `field.Error` immediately after the control or inside `field.Content` to keep error messages aligned with the field.

```templ showLineNumbers /data-invalid/
@field.Field(field.Props{Attributes: templ.Attributes{"data-invalid": "true"}}) {
	@field.Label(field.LabelProps{For: "email"}) {
		Email
	}
	@input.Input(input.Props{ID: "email", Type: "email", Attributes: templ.Attributes{"aria-invalid": "true"}})
	@field.Error() {
		Enter a valid email address.
	}
}
```

## Accessibility

- `field.Set` and `field.Legend` keep related controls grouped for keyboard and assistive tech users.
- `Field` outputs `role="group"` so nested controls inherit labeling from `field.Label` and `field.Legend` when combined.
- Apply `field.Separator` sparingly to ensure screen readers encounter clear section boundaries.

## API Reference

### FieldSet

Container that renders a semantic `fieldset` with spacing presets.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Set() {
	@field.Legend() {
		Delivery
	}
	@field.Group() {
		// Fields
	}
}
```

### FieldLegend

Legend element for a `field.Set`. Switch to the `label` variant to align with label sizing.

| Prop      | Type                                        | Default               |
| --------- | ------------------------------------------- | --------------------- |
| `Variant` | `LegendVariantLegend \| LegendVariantLabel` | `LegendVariantLegend` |
| `Class`   | `string`                                    | -                     |

```templ
@field.Legend(field.LegendProps{Variant: field.LegendVariantLabel}) {
	Notification Preferences
}
```

The `field.Legend` has two variants: `legend` and `label`. The `label` variant applies label sizing and alignment. Handy if you have nested `field.Set`.

### FieldGroup

Layout wrapper that stacks `field.Field` components and enables container queries for responsive orientations.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Group(field.GroupProps{Class: "@container/field-group flex flex-col gap-6"}) {
	@field.Field() {
		// ...
	}
	@field.Field() {
		// ...
	}
}
```

### Field

The core wrapper for a single field. Provides orientation control and spacing; mark states with `data-invalid` / `data-disabled` attributes.

| Prop          | Type                                                                     | Default               |
| ------------- | ------------------------------------------------------------------------ | --------------------- |
| `Orientation` | `OrientationVertical \| OrientationHorizontal \| OrientationResponsive` | `OrientationVertical` |
| `Class`       | `string`                                                                 | -                     |

```templ
@field.Field(field.Props{Orientation: field.OrientationHorizontal}) {
	@field.Label(field.LabelProps{For: "remember"}) {
		Remember me
	}
	@switchcomp.Switch(switchcomp.Props{ID: "remember"})
}
```

### FieldContent

Flex column that groups control and descriptions when the label sits beside the control. Not required if you have no description.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Field() {
	@checkbox.Checkbox(checkbox.Props{ID: "notifications"})
	@field.Content() {
		@field.Label(field.LabelProps{For: "notifications"}) {
			Notifications
		}
		@field.Description() {
			Email, SMS, and push options.
		}
	}
}
```

### FieldLabel

Label styled for both direct inputs and nested `field.Field` children.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `For`   | `string` | -       |
| `Class` | `string` | -       |

```templ
@field.Label(field.LabelProps{For: "email"}) {
	Email
}
```

### FieldTitle

Renders a title with label styling inside `field.Content`.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Content() {
	@field.Title() {
		Enable Touch ID
	}
	@field.Description() {
		Unlock your device faster.
	}
}
```

### FieldDescription

Helper text slot that automatically balances long lines in horizontal layouts.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Description() {
	We never share your email with anyone.
}
```

### FieldSeparator

Visual divider to separate sections inside a `field.Group`. Accepts optional inline content.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Separator() {
	Or continue with
}
```

### FieldError

Accessible error container for validation messages.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |

```templ
@field.Error() {
	Choose another username.
}
```
