Summary
When EuiComboBox is given a delimiter, pasting a delimited (or copied multi-value) string does not reliably create one option per value. In common cases it collapses everything into a single option/pill. Copy→paste of a list of tags is a very frequent user expectation, so it would be great if EuiComboBox handled it natively when a delimiter is configured.
EUI version: 116.5.0
Component: EuiComboBox
Current behavior
Two separate problems combine to break paste:
-
The search field is a single-line <input>, which sanitizes pasted text before EUI sees it.
In combo_box_input.tsx the input only receives values via onChange(event.target.value). Per the HTML value-sanitization algorithm, a single-line <input> strips/normalizes newlines. So when a user copies rendered tag badges (block-level elements, which land on the clipboard newline-separated) and pastes them, the newlines are gone (stripped, or collapsed to spaces depending on browser) before onChange/onSearchChange runs. The delimiter is destroyed and the whole thing becomes one value. Even a delimiter="," doesn't help, because the pasted text never contained commas.
-
The delimiter split path calls onCreateOption once per value in a synchronous loop.
In combo_box.tsx, setCustomOptions (called on Enter/blur, and from onSearchChange when the value endsWith(delimiter)) does:
values.forEach((option) => addCustomOption(isContainerBlur, option));
Each addCustomOption calls onCreateOption(value, ...). Consumers that derive the next state from a captured/controlled value (react-hook-form field.onChange, useReducer dispatch, setState([...prev, x]) with a stale closure) end up dropping all but the last value, because the loop runs synchronously before any re-render.
Expected behavior
When delimiter is provided, pasting a list of values should create one option/pill per value in a single update — including when the clipboard is newline-separated (the natural result of copying rendered pills/badges).
Reproduction
- Render an
EuiComboBox with delimiter=",", onCreateOption, and a controlled selectedOptions (e.g. via react-hook-form).
- Copy several rendered tags/badges (or any newline-separated list) to the clipboard.
- Focus the combo box and paste, then blur/Enter.
Actual: a single option containing the concatenated text (e.g. tag1tag2tag3 or tag1 tag2 tag3).
Expected: tag1, tag2, tag3 as separate options.
Proposal
- Add an
onPaste handler in EuiComboBoxInput that, when delimiter is set, reads the raw clipboardData.getData('text') before the input sanitizes it, splits on the configured delimiter and newlines, and creates all resulting options in one pass (calling preventDefault()).
- To avoid the stale-closure problem when creating multiple options at once, either batch the created values and surface them together (e.g. a single
onCreateOption(values: string[]) / multi-create callback), or have EUI accumulate the created options internally before invoking the consumer once.
Context
Real-world case: users copy tags from an existing item (rendered as badges) and paste them into a new item's tags field; they end up with one giant tag. We're currently working around this in Kibana by adding a per-consumer onPaste handler that reads the raw clipboard and splits on /[\n\r,]+/, but this really belongs in EuiComboBox when a delimiter is provided.
Summary
When
EuiComboBoxis given adelimiter, pasting a delimited (or copied multi-value) string does not reliably create one option per value. In common cases it collapses everything into a single option/pill. Copy→paste of a list of tags is a very frequent user expectation, so it would be great ifEuiComboBoxhandled it natively when adelimiteris configured.EUI version:
116.5.0Component:
EuiComboBoxCurrent behavior
Two separate problems combine to break paste:
The search field is a single-line
<input>, which sanitizes pasted text before EUI sees it.In
combo_box_input.tsxthe input only receives values viaonChange(event.target.value). Per the HTML value-sanitization algorithm, a single-line<input>strips/normalizes newlines. So when a user copies rendered tag badges (block-level elements, which land on the clipboard newline-separated) and pastes them, the newlines are gone (stripped, or collapsed to spaces depending on browser) beforeonChange/onSearchChangeruns. The delimiter is destroyed and the whole thing becomes one value. Even adelimiter=","doesn't help, because the pasted text never contained commas.The
delimitersplit path callsonCreateOptiononce per value in a synchronous loop.In
combo_box.tsx,setCustomOptions(called on Enter/blur, and fromonSearchChangewhen the valueendsWith(delimiter)) does:Each
addCustomOptioncallsonCreateOption(value, ...). Consumers that derive the next state from a captured/controlled value (react-hook-formfield.onChange,useReducerdispatch,setState([...prev, x])with a stale closure) end up dropping all but the last value, because the loop runs synchronously before any re-render.Expected behavior
When
delimiteris provided, pasting a list of values should create one option/pill per value in a single update — including when the clipboard is newline-separated (the natural result of copying rendered pills/badges).Reproduction
EuiComboBoxwithdelimiter=",",onCreateOption, and a controlledselectedOptions(e.g. via react-hook-form).Actual: a single option containing the concatenated text (e.g.
tag1tag2tag3ortag1 tag2 tag3).Expected:
tag1,tag2,tag3as separate options.Proposal
onPastehandler inEuiComboBoxInputthat, whendelimiteris set, reads the rawclipboardData.getData('text')before the input sanitizes it, splits on the configured delimiter and newlines, and creates all resulting options in one pass (callingpreventDefault()).onCreateOption(values: string[])/ multi-create callback), or have EUI accumulate the created options internally before invoking the consumer once.Context
Real-world case: users copy tags from an existing item (rendered as badges) and paste them into a new item's tags field; they end up with one giant tag. We're currently working around this in Kibana by adding a per-consumer
onPastehandler that reads the raw clipboard and splits on/[\n\r,]+/, but this really belongs inEuiComboBoxwhen adelimiteris provided.