# SearchingInput

> Slug: `searching-input` · Category: Form Controls

## When to use

- ONLY as the input slot of a `MenuDropdown` with `variant="searching"`. It is a context-aware input that wires combobox ARIA attributes (`aria-controls`, `aria-labelledby`, `aria-expanded`).
- When the user filters items in a dropdown via type-ahead.

## When NOT to use

- Standalone search bar above a list — use `Search`.
- Plain text entry — use `TextField`.
- A typeable combobox without a search icon — use `TextingInput`.

## Variants & decision tree

`SearchingInput` renders a leading search icon and a conditional clear button (visible only when `value` is non-empty). It is intentionally minimal because the surrounding `MenuDropdown` owns the menu, label, and selection logic.

## States

Empty, focused, filled (clear button visible), disabled, invalid (error styling), expanded (menu open).

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `id` | `string` | — | Required. Input element id. |
| `menuId` | `string` | — | Required. `aria-controls` target — the dropdown menu's id. |
| `labelId` | `string` | — | Required. `aria-labelledby` target — the visible label's id. |
| `isExpanded` | `boolean` | — | Required. Whether the menu is open. |
| `value` | `string` | — | Current value (controls clear-button visibility). |
| `onClear` | `() => void` | — | Fired when × is clicked. |
| `disabled` | `boolean` | `false` | Disabled (uses `aria-disabled` + `readOnly`). |
| `isInvalid` | `boolean` | `false` | Error styling. |
| `describedBy` | `string` | — | Space-separated ids for `aria-describedby`. |
| `searchIcon` / `clearIcon` | `ReactNode` | built-in | Override default SVGs. |
| `clearButtonLabel` | `string` | — | a11y label for clear button. |
| `inverse` | `boolean` | `false` | Dark-background styling. |

## Usage examples

```tsx
// Inside MenuDropdown, prefer the high-level prop API:
<MenuDropdown
  id="city"
  label="City"
  variant="searching"
  menuItems={filteredCities}
  value={query}
  onValueChange={setQuery}
  onClear={() => setQuery('')}
  onItemSelect={(item) => selectCity(item)}
/>

// Standalone usage (rare — ensure surrounding ARIA wiring):
<SearchingInput
  id="city-input"
  menuId="city-menu"
  labelId="city-label"
  isExpanded={open}
  value={q}
  onChange={(e) => setQ(e.target.value)}
  onClear={() => setQ('')}
/>
```

## Composition

Pair with a labeled `MenuDropdown` (preferred) — `MenuDropdown variant="searching"` already composes this internally. Direct use is rare and reserved for custom combobox shells.

## Accessibility

Combobox role, `aria-controls`, `aria-labelledby`, and `aria-expanded` are wired via the required props. You MUST provide a label element with the `labelId` and a menu container with the `menuId`. `disabled` correctly applies `aria-disabled` + `readOnly` so the input remains in the focus order and announces its state.

## Do / Don't

- DO prefer `MenuDropdown variant="searching"` instead of using this directly.
- DO provide all three id props (`id`, `menuId`, `labelId`).
- DON'T use this as a generic search bar — that's `Search`.
- DON'T omit `isExpanded` — it drives the combobox state announcement.
