Controlled inline search field that replaces the chat panel header's title area when search is active, debouncing typed input before emitting it to the host for server-side refetching.
## Key Components
### `ChatHeaderSearchField`
The primary export. Renders a leading `SearchIcon` alongside a borderless, full-height `` that takes over the header title slot. Manages its own text state locally for snappy typing, then propagates the debounced query (300 ms) via `onSearchChange`.
**Collapse lifecycle** — exit animations are coordinated manually:
1. `beginCollapse()` sets `exiting = true`, disabling the input and triggering CSS leave animations.
2. `finishCollapse()` is called on `animationend` of the root element (bubbled child events are ignored).
3. A 240 ms `setTimeout` fallback fires `finishCollapse` when `animationend` never fires (reduced-motion or stripped utilities).
**Stale-debounce guard** — when Escape is pressed or the field blurs empty, the cleared term is emitted synchronously and recorded in `lastEmitted`, preventing the still-pending 300 ms debounce from triggering a redundant server round-trip after unmount begins.
### `ChatHeaderSearchFieldProps`
| Prop | Type | Default | Description |
|---|---|---|---|
| `initialValue` | `string` | `''` | Seeds the input on mount |
| `onSearchChange` | `(query: string) => void` | — | Receives the debounced search term |
| `onCollapse` | `() => void` | — | Called after the leave animation completes |
| `autoFocus` | `boolean` | `true` | Focuses the input on mount |
| `className` | `string` | — | Appended to the root element |
## Usage Example
```typescript
import { ChatHeaderSearchField } from './chat-header-search-field'
function ChatPanelHeader() {
const [searchOpen, setSearchOpen] = React.useState(false)
const [query, setQuery] = React.useState('')
return (
{searchOpen ? (
setQuery(term)}
onCollapse={() => setSearchOpen(false)}
/>
) : (