# Forms & Inputs
## Contents
- Forms use Field.FieldGroup + Field.Field
- InputGroup requires InputGroup.Input/InputGroup.Textarea
- Buttons inside inputs use InputGroup.Root + InputGroup.Addon
- Option sets (2–7 choices) use ToggleGroup.Root + ToggleGroup.Item
- Field.FieldSet + Field.FieldLegend for grouping related fields
- Field validation and disabled states
---
## Forms use Field.FieldGroup + Field.Field
Always use `Field.FieldGroup` + `Field.Field` — never raw `div` with `space-y-*`:
```svelte
EmailPassword
```
Use `Field` with `orientation="horizontal"` for settings pages. Use `Field.FieldLabel` with `class="sr-only"` for visually hidden labels.
**Choosing form controls:**
- Simple text input → `Input`
- Dropdown with predefined options → `Select`
- Searchable dropdown → `Combobox`
- Native HTML select (no JS) → `native-select`
- Boolean toggle → `Switch` (for settings) or `Checkbox` (for forms)
- Single choice from few options → `RadioGroup`
- Toggle between 2–5 options → `ToggleGroup.Root` + `ToggleGroup.Item`
- OTP/verification code → `InputOTP`
- Multi-line text → `Textarea`
---
## InputGroup requires InputGroup.Input/InputGroup.Textarea
Never use raw `Input` or `Textarea` inside an `InputGroup.Root`.
**Incorrect:**
```svelte
```
**Correct:**
```svelte
```
---
## Buttons inside inputs use InputGroup.Root + InputGroup.Addon
Never place a `Button` directly inside or adjacent to an `Input` with custom positioning.
**Incorrect:**
```svelte
```
**Correct:**
```svelte
```
---
## Option sets (2–7 choices) use ToggleGroup.Root + ToggleGroup.Item
Don't manually loop `Button` components with active state.
**Incorrect:**
```svelte
{#each ["daily", "weekly", "monthly"] as option (option)}
{/each}
```
**Correct:**
```svelte
DailyWeeklyMonthly
```
Combine with `Field` for labelled toggle groups:
```svelte
ThemeLightDarkSystem
```
---
## Field.FieldSet + Field.FieldLegend for grouping related fields
Use `Field.FieldSet` + `Field.FieldLegend` for related checkboxes, radios, or switches — not `div` with a heading:
```svelte
PreferencesSelect all that apply.Dark mode
```
---
## Field validation and disabled states
Both attributes are needed — `data-invalid`/`data-disabled` styles the field (label, description), while `aria-invalid`/`disabled` styles the control.
```svelte
EmailInvalid email address.Email
```
Works for all controls: `Input`, `Textarea`, `Select`, `Checkbox`, `RadioGroupItem`, `Switch`, `Slider`, `NativeSelect`, `InputOTP`.