[EuiSearchBar] Surface change source on `onChange` so consumers can distinguish typing from custom-filter changes
- Dominant language
- TypeScript
- Stars
- 6.4k
- Forks
- 911
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 65
Description
## Problem
[`EuiSearchBar.onChange`](https://github.com/elastic/eui/blob/main/src/components/search_bar/search_bar.tsx) is invoked from two internal entry points — `onSearch` (free-text typing) and `onFiltersChange` (a `custom_component` filter calling its provided `onChange`) — but both funnel through `notifyControllingParent`, which only forwards `{ query, queryText, error }` to the consumer. The consumer cannot tell which path produced the change.
## Use case
In [`@kbn/content-list-toolbar`](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/content-management/content_list/kbn-content-list-toolbar/src/hooks/use_filters.ts), Content List drives URL persistence via `history.push` vs `history.replace`:
- Typing keystrokes → `history.replace` (don't create one history entry per character).
- Committed filter actions → `history.push` (Back/Forward should move between filter states).
Because EUI doesn't expose the source, the toolbar currently has to *wrap each `custom_component` filter* in a tiny HOC that intercepts `onChange` before EUI sees it, dispatches with `source: 'filter'`, and bypasses EUI's controlled-state notification entirely. A `WeakMap` cache is needed because `CustomComponentFilter` renders `config.component` directly, so a fresh wrapper per recompute would unmount/remount each filter's internals (popover state, debounce timers, in-flight facet queries).
## Proposal
Plumb a `source` discriminator through `notifyControllingParent` into the consumer's `onChange`:
```ts
onChange?: (args: {
query: Query | null;
queryText: string;
error: Error | null;
source: 'search' | 'filters'; // new
}) => void;
```
Alternatively, expose a separate `onFiltersChange` prop so the typing path and filter path stay distinct from the top.
Either change would let `@kbn/content-list-toolbar` (and any other consumer that cares about intent) drop the per-component wrapper and the `WeakMap` cache, collapsing `use_filters.ts` to a single `handleSearchChange` that branches on `args.source`.
## Workaround in tree
See `wrapperCache` / `getWrappedFilterComponent` / `wrapCustomFilters` in [`use_filters.ts`](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/content-management/content_list/kbn-content-list-toolbar/src/hooks/use_filters.ts), and the originating discussion at [elastic/kibana#267632 (comment)](https://github.com/elastic/kibana/pull/267632#discussion_r3219409386).
Contributor guide
Assessment
This issue has not been assessed yet.