Skip to content

[EuiComboBox] Pasting a delimited/copied list of values doesn't create multiple options #9806

Description

@shahzad31

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:

  1. 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.

  2. 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

  1. Render an EuiComboBox with delimiter=",", onCreateOption, and a controlled selectedOptions (e.g. via react-hook-form).
  2. Copy several rendered tags/badges (or any newline-separated list) to the clipboard.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions