# Input Group

Grouped input primitives for prefixes, suffixes, stacked helper rows, and inline actions.

Use Input Group when the field and its addon content should read as a single control boundary instead of separate neighboring elements.

## Import

```ts
import {
  FormControlDirective,
  FormDescriptionComponent,
  FormFieldComponent,
  FormLabelComponent,
} from '@edsis/component/form';
import {
  InputGroupAddonComponent,
  InputGroupButtonComponent,
  InputGroupComponent,
  InputGroupInputComponent,
  InputGroupTextComponent,
  InputGroupTextareaComponent,
} from '@edsis/component/input-group';
```

## Usage

Keep the input or textarea first in the DOM, then append one or more addons after it.
Use the `align` input on `InputGroupAddon` to place the addon at the inline or block edge.

```html
<FormField>
  <FormLabel>Search</FormLabel>
  <InputGroup>
    <input InputGroupInput FormControl placeholder="Search documentation..." />
    <InputGroupAddon>
      <span aria-hidden="true">⌕</span>
    </InputGroupAddon>
    <InputGroupAddon align="inline-end">
      <InputGroupText>12 results</InputGroupText>
    </InputGroupAddon>
  </InputGroup>
  <FormDescription
    >Keep addons after the control in the DOM and use align for visual placement.</FormDescription
  >
</FormField>
```

## Composition

```text
InputGroup
├── input[InputGroupInput] or textarea[InputGroupTextarea]
├── InputGroupAddon
│   ├── InputGroupText
│   └── button[InputGroupButton]
└── InputGroupAddon
```

## Common Patterns

### Inline search

```html
<InputGroup class="max-w-md">
  <input InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <span aria-hidden="true">⌕</span>
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <InputGroupText>12 results</InputGroupText>
  </InputGroupAddon>
</InputGroup>
```

### Text addons

```html
<InputGroup>
  <input InputGroupInput placeholder="0.00" />
  <InputGroupAddon>
    <InputGroupText>$</InputGroupText>
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <InputGroupText>USD</InputGroupText>
  </InputGroupAddon>
</InputGroup>
```

### Textarea footer

```html
<InputGroup>
  <textarea InputGroupTextarea placeholder="Write a comment..."></textarea>
  <InputGroupAddon align="block-end">
    <InputGroupText>0/280</InputGroupText>
    <button InputGroupButton type="button" size="sm" variant="default" class="ml-auto">Post</button>
  </InputGroupAddon>
</InputGroup>
```

### Custom control

```html
<InputGroup>
  <textarea
    data-slot="input-group-control"
    class="min-h-20 w-full resize-none bg-transparent px-3 py-2.5 text-sm outline-none placeholder:text-muted-foreground"
    placeholder="Use any custom control that matches the group contract..."
  ></textarea>
  <InputGroupAddon align="block-end">
    <button InputGroupButton type="button" variant="default" size="sm" class="ml-auto">
      Submit
    </button>
  </InputGroupAddon>
</InputGroup>
```

### Keyboard shortcut badge

```html
<InputGroup class="max-w-sm">
  <input InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <span aria-hidden="true">⌕</span>
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <span
      aria-hidden="true"
      class="inline-flex h-6 items-center rounded-md border border-border bg-background px-2 font-mono text-[11px] font-medium text-foreground shadow-sm"
    >
      ⌘K
    </span>
  </InputGroupAddon>
</InputGroup>
```

### Dropdown composition

Use the local menu primitives when the grouped field needs scoped actions or search destinations.

```html
<InputGroup>
  <input InputGroupInput placeholder="Enter file name" />
  <InputGroupAddon align="inline-end">
    <button
      InputGroupButton
      type="button"
      size="icon-xs"
      aria-label="Open file actions"
      [MenuTrigger]="fileActionsMenu"
    >
      ⋯
    </button>
  </InputGroupAddon>
</InputGroup>

<ng-template MenuContent #fileActionsMenu="MenuContent">
  <MenuSurface>
    <MenuLabel>File actions</MenuLabel>
    <button MenuItem type="button">Settings</button>
    <button MenuItem type="button">Copy path</button>
    <MenuSeparator />
    <button MenuItem type="button">Open location</button>
  </MenuSurface>
</ng-template>
```

### Spinner status row

```html
<InputGroup>
  <input InputGroupInput placeholder="Saving changes..." />
  <InputGroupAddon align="inline-end">
    <InputGroupText>Saving...</InputGroupText>
    <span
      aria-hidden="true"
      class="inline-flex size-4 animate-spin rounded-full border-2 border-muted border-t-foreground"
    ></span>
  </InputGroupAddon>
</InputGroup>
```

## API Reference

### `InputGroupComponent`

| Input   | Type     | Default      |
| ------- | -------- | ------------ |
| `class` | `string` | empty string |

### `InputGroupAddonComponent`

| Input   | Type                                                          | Default          |
| ------- | ------------------------------------------------------------- | ---------------- |
| `align` | `'inline-start', 'inline-end', 'block-start', or 'block-end'` | `'inline-start'` |
| `class` | `string`                                                      | empty string     |

### `InputGroupButtonComponent`

| Input     | Type                                  | Default      |
| --------- | ------------------------------------- | ------------ |
| `variant` | `ButtonVariant`                       | `'ghost'`    |
| `size`    | `'xs', 'icon-xs', 'sm', or 'icon-sm'` | `'xs'`       |
| `class`   | `string`                              | empty string |

### `InputGroupInputComponent` and `InputGroupTextareaComponent`

| Input   | Type     | Default      |
| ------- | -------- | ------------ |
| `class` | `string` | empty string |

All other native input and textarea attributes pass through unchanged.

## Styling And Theming

- `InputGroup` owns the shared border, focus ring, radius, and background surface.
- `InputGroupAddon` uses logical separators so start and end alignments still read correctly in RTL layouts.
- Override `--radius` on the group root when the grouped field should be sharper or more pill-shaped.
- Add spacing or typography utilities through `class` on any primitive without breaking the core layout contract.

## Accessibility

- Keep the input or textarea before addons in the DOM so tab order and assistive reading order stay predictable.
- Provide a visible label with `FormLabel`, `Label`, or another accessible name source.
- Give icon-only `InputGroupButton` elements an `aria-label`.
- Use `FormControl` inside `FormField` when labels, descriptions, and invalid messaging should auto-wire to the grouped control.

## Keyboard Interactions

- Text input and textarea editing remain native.
- Buttons inside addons participate in the normal tab sequence after the text control.
- Changing `align` only affects visual placement; it does not change keyboard order.

## Angular Notes

- `InputGroupInput` and `InputGroupTextarea` are attribute selectors on native controls, so native input and textarea behavior remains intact.
- For custom controls, set `data-slot="input-group-control"` and provide your own spacing utilities so the wrapper can still coordinate focus and addon layout.
- Upstream shadcn `Field` examples map to the local `FormField`, `FormLabel`, and `FormDescription` primitives rather than a separate `field` runtime component.

## Source Parity

This Angular implementation covers the core shadcn Input Group primitives, all four addon alignments, textarea support, custom control guidance, and RTL composition.

Keyboard shortcut badges, dropdown triggers, and spinner/status rows are composed from the same primitives plus the local menu surface and inline status markup instead of requiring input-group-specific wrappers.
