From 2b1ab441e384a2a10296cc66646590ff53143e0b Mon Sep 17 00:00:00 2001 From: lostElk Date: Sat, 14 Feb 2026 07:00:16 +0800 Subject: [PATCH] feat(components): [select/select-v2] add `tag-tooltip` config object prop (#23556) * feat(components): [select] add collapseTagsTooltipAppendTo & test Add collapseTagsTooltipAppendTo prop to control where the collapse-tags tooltip is appended. Wire it to the tag tooltip with fallback to appendTo. Add unit test to verify prop is passed correctly. * docs(docs): add collapseTagsTooltipAppendTo doc * refactor(components): [select]rename collapseTagsTooltipAppendTo prop Rename collapseTagsTooltipAppendTo to tooltipAppendTo Simplify the prop name by removing redundant context Behavior remains unchanged * docs(components): [select] add version tag for tooltipAppendTo prop * Update packages/components/select/__tests__/select.test.ts Co-authored-by: rzzf * feat(components): [select] add tagTooltip config object Add TagTooltip to support appendTo, placement, fallbackPlacements, effect, popperClass, popperStyle, teleported, popperOptions, showAfter, and offsetWire all tagTooltip properties to the collapse-tags tooltip with fallback to existing select propsProvides more granular control over tooltip behavior while maintaining backward compatibility * docs(components): [select] add tag-tooltip config object doc * docs(components): [select] add default value for fallback-placements * docs(components): [select] update tag-tooltip default value to {} * docs(components): [select]remove string type from TagTooltipProps effect * docs(components): [select] add fallback mechanism tip for tag-tooltip * feat(components): [select] extend TagTooltipProps Add transition, hideAfter, and autoClose properties to TagTooltipProps Update popperStyle type to accept both string and CSSProperties * docs(components): [select] enhance tag-tooltip documentation Add transition, hide-after, and auto-close properties to TagTooltip API table Clarify fallback mechanism with priority order explanation Add custom container positioning tip for append-to usage * docs(components): [select] refine tag-tooltip priority description Co-authored-by: keeplearning66 <1256734885@qq.com> * docs(components): [select] refine effect prop type in tag-tooltip Co-authored-by: keeplearning66 <1256734885@qq.com> * chore: format * docs: apply rabbit comment * feat(components): [select-v2] add TagTooltipProps interface Add TagTooltipProps interface with popper configuration options * feat(components): [select-v2] implement tagTooltip prop * test(components): [select-v2] add tag-tooltip prop test case Add test case to verify tagTooltip prop functionality with appendTo option * docs(components): [select-v2] add tag-tooltip API documentation Add tag-tooltip configuration object to Select V2 API table Add comprehensive tag-tooltip properties section with fallback mechanism explanation and custom container positioning tip * docs(components): [select-v2] add version tag to tag-tooltip prop * fix(components): [select-v2] Optional chain tagTooltip access * fix(components): [select] optional chain tagTooltip access * feat(components): [select-v2] Fix tooltip teleport timing * docs(components): [select-v] add version tag for tag-tooltip Co-authored-by: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> * docs(components): [select] add version tag for tag-tooltip Co-authored-by: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> --------- Co-authored-by: rzzf Co-authored-by: keeplearning66 <1256734885@qq.com> Co-authored-by: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com> --- docs/en-US/component/select-v2.md | 150 +++++++++++------- docs/en-US/component/select.md | 144 ++++++++++------- .../select-v2/__tests__/select.test.ts | 40 +++++ packages/components/select-v2/src/defaults.ts | 32 +++- packages/components/select-v2/src/select.vue | 33 ++-- .../select/__tests__/select.test.ts | 22 ++- packages/components/select/src/select.ts | 26 +++ packages/components/select/src/select.vue | 27 +++- 8 files changed, 342 insertions(+), 132 deletions(-) diff --git a/docs/en-US/component/select-v2.md b/docs/en-US/component/select-v2.md index daeabf2e2a..d4415fc77f 100644 --- a/docs/en-US/component/select-v2.md +++ b/docs/en-US/component/select-v2.md @@ -235,63 +235,64 @@ select-v2/custom-width ### Attributes -| Name | Description | Type | Default | -| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] / ^[object] / ^[array] | — | -| options | data of the options, the key of `value` and `label` can be customize by `props` | ^[array] | — | -| [props](#props) ^(2.4.2) | configuration options, see the following table | ^[object] | — | -| multiple | is multiple | ^[boolean] | false | -| disabled | is disabled | ^[boolean] | false | -| value-key | unique identity key name for value, required when value is an object | ^[string] | value | -| size | size of component | ^[enum]`'' \| 'large' \| 'default' \| 'small'` | '' | -| clearable | whether select can be cleared | ^[boolean] | false | -| clear-icon | custom clear icon | ^[string] / ^[object]`Component` | CircleClose | -| collapse-tags | whether to collapse tags to a text when multiple selecting | ^[boolean] | false | -| multiple-limit | maximum number of options user can select when multiple is true. No limit when set to 0 | ^[number] | 0 | -| id | native input id input | ^[string] | — | -| name | the name attribute of select input | ^[string] | — | -| effect | tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | light | -| autocomplete | autocomplete of select input | ^[string] | off | -| placeholder | placeholder | ^[string] | Please select | -| filterable | whether Select is filterable | ^[boolean] | false | -| allow-create | whether creating new items is allowed. To use this, `filterable` must be true | ^[boolean] | false | -| filter-method | custom filter method, the first parameter is the current input value. To use this, `filterable` must be true method | ^[Function]`(query: string) => void` | — | -| loading | whether Select is loading data from server | ^[boolean] | false | -| loading-text | displayed text while loading data from server, default is 'Loading' | ^[string] | — | -| reserve-keyword | whether reserve the keyword after select filtered option. | ^[boolean] | true | -| default-first-option | select first matching option on enter key. Use with `filterable` or `remote` | ^[boolean] | false | -| no-match-text | displayed text when no data matches the filtering query, you can also use slot `empty`, default is 'No matching data' | ^[string] | — | -| no-data-text | displayed text when there is no options, you can also use slot empty | ^[string] | No Data | -| popper-class | custom class name for Select's dropdown and tags' tooltip | ^[string] / ^[object] | '' | -| popper-style ^(2.11.0) | custom style for Select's dropdown and tags' tooltip | ^[string] / ^[object] | — | -| teleported | whether select dropdown is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | true | -| append-to ^(2.8.8) | which element the select dropdown appends to | ^[CSSSelector] / ^[HTMLElement] | — | -| persistent | when select dropdown is inactive and `persistent` is `false`, select dropdown will be destroyed | ^[boolean] | true | -| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | {} | -| automatic-dropdown | for non-filterable Select, this prop decides if the option menu pops up when the input is focused | ^[boolean] | false | -| fit-input-width ^(2.9.2) | whether the width of the dropdown is the same as the input, if the value is `number`, then the width is fixed | ^[boolean] / ^[number] | true | -| suffix-icon ^(2.9.8) | custom suffix icon component | ^[string] / ^[object]`Component` | ArrowDown | -| height | The height of the dropdown panel, 34px for each item | ^[number] | 274 | -| item-height | The height of the dropdown item | ^[number] | 34 | -| scrollbar-always-on | Controls whether the scrollbar is always displayed | ^[boolean] | false | -| remote | whether search data from server | ^[boolean] | false | -| debounce ^(2.11.7) | debounce delay during remote search, in milliseconds | ^[number] | 300 | -| remote-method | function that gets called when the input value changes. Its parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | -| remote-show-suffix ^(2.11.9) | in remote search method show suffix icon | ^[boolean] | false | -| validate-event | whether to trigger form validation | ^[boolean] | true | -| offset ^(2.8.8) | offset of the dropdown | ^[number] | 12 | -| show-arrow ^(2.8.8) | whether the dropdown has an arrow | ^[boolean] | true | -| placement | position of dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom-start | -| fallback-placements ^(2.5.6) | list of possible positions for dropdown [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom-start', 'top-start', 'right', 'left'] | -| collapse-tags-tooltip ^(2.3.0) | whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true | ^[boolean] | false | -| max-collapse-tags ^(2.3.0) | The max tags number to be shown. To use this, `collapse-tags` must be true | ^[number] | 1 | -| tag-type ^(2.5.0) | tag type | ^[enum]`'' \| 'success' \| 'info' \| 'warning' \| 'danger'` | info | -| tag-effect ^(2.7.7) | tag effect | ^[enum]`'' \| 'light' \| 'dark' \| 'plain'` | light | -| aria-label ^(a11y) ^(2.5.0) | same as `aria-label` in native input | ^[string] | — | -| empty-values ^(2.7.0) | empty values of component, [see config-provider](./config-provider.md#empty-values-configurations) | ^[array] | — | -| value-on-clear ^(2.7.0) | clear return value, [see config-provider](./config-provider.md#empty-values-configurations) | ^[string] / ^[number] / ^[boolean] / ^[Function] | — | -| popper-append-to-body ^(deprecated) | whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false | ^[boolean] | false | -| tabindex ^(2.9.0) | tabindex for input | ^[string] / ^[number] | — | +| Name | Description | Type | Default | +| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | +| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] / ^[object] / ^[array] | — | +| options | data of the options, the key of `value` and `label` can be customize by `props` | ^[array] | — | +| [props](#props) ^(2.4.2) | configuration options, see the following table | ^[object] | — | +| multiple | is multiple | ^[boolean] | false | +| disabled | is disabled | ^[boolean] | false | +| value-key | unique identity key name for value, required when value is an object | ^[string] | value | +| size | size of component | ^[enum]`'' \| 'large' \| 'default' \| 'small'` | '' | +| clearable | whether select can be cleared | ^[boolean] | false | +| clear-icon | custom clear icon | ^[string] / ^[object]`Component` | CircleClose | +| collapse-tags | whether to collapse tags to a text when multiple selecting | ^[boolean] | false | +| multiple-limit | maximum number of options user can select when multiple is true. No limit when set to 0 | ^[number] | 0 | +| id | native input id input | ^[string] | — | +| name | the name attribute of select input | ^[string] | — | +| effect | tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | light | +| autocomplete | autocomplete of select input | ^[string] | off | +| placeholder | placeholder | ^[string] | Please select | +| filterable | whether Select is filterable | ^[boolean] | false | +| allow-create | whether creating new items is allowed. To use this, `filterable` must be true | ^[boolean] | false | +| filter-method | custom filter method, the first parameter is the current input value. To use this, `filterable` must be true method | ^[Function]`(query: string) => void` | — | +| loading | whether Select is loading data from server | ^[boolean] | false | +| loading-text | displayed text while loading data from server, default is 'Loading' | ^[string] | — | +| reserve-keyword | whether reserve the keyword after select filtered option. | ^[boolean] | true | +| default-first-option | select first matching option on enter key. Use with `filterable` or `remote` | ^[boolean] | false | +| no-match-text | displayed text when no data matches the filtering query, you can also use slot `empty`, default is 'No matching data' | ^[string] | — | +| no-data-text | displayed text when there is no options, you can also use slot empty | ^[string] | No Data | +| popper-class | custom class name for Select's dropdown and tags' tooltip | ^[string] / ^[object] | '' | +| popper-style ^(2.11.0) | custom style for Select's dropdown and tags' tooltip | ^[string] / ^[object] | — | +| teleported | whether select dropdown is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | true | +| append-to ^(2.8.8) | which element the select dropdown appends to | ^[CSSSelector] / ^[HTMLElement] | — | +| persistent | when select dropdown is inactive and `persistent` is `false`, select dropdown will be destroyed | ^[boolean] | true | +| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | {} | +| automatic-dropdown | for non-filterable Select, this prop decides if the option menu pops up when the input is focused | ^[boolean] | false | +| fit-input-width ^(2.9.2) | whether the width of the dropdown is the same as the input, if the value is `number`, then the width is fixed | ^[boolean] / ^[number] | true | +| suffix-icon ^(2.9.8) | custom suffix icon component | ^[string] / ^[object]`Component` | ArrowDown | +| height | The height of the dropdown panel, 34px for each item | ^[number] | 274 | +| item-height | The height of the dropdown item | ^[number] | 34 | +| scrollbar-always-on | Controls whether the scrollbar is always displayed | ^[boolean] | false | +| remote | whether search data from server | ^[boolean] | false | +| debounce ^(2.11.7) | debounce delay during remote search, in milliseconds | ^[number] | 300 | +| remote-method | function that gets called when the input value changes. Its parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | +| remote-show-suffix ^(2.11.9) | in remote search method show suffix icon | ^[boolean] | false | +| validate-event | whether to trigger form validation | ^[boolean] | true | +| offset ^(2.8.8) | offset of the dropdown | ^[number] | 12 | +| show-arrow ^(2.8.8) | whether the dropdown has an arrow | ^[boolean] | true | +| placement | position of dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom-start | +| fallback-placements ^(2.5.6) | list of possible positions for dropdown [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom-start', 'top-start', 'right', 'left'] | +| collapse-tags-tooltip ^(2.3.0) | whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true | ^[boolean] | false | +| [tag-tooltip](#tag-tooltip) ^(2.13.3) | configuration object for the collapse-tags tooltip. To use this, `collapse-tags` and `collapse-tags-tooltip` must be true | ^[object]`TagTooltipProps` | {} | +| max-collapse-tags ^(2.3.0) | The max tags number to be shown. To use this, `collapse-tags` must be true | ^[number] | 1 | +| tag-type ^(2.5.0) | tag type | ^[enum]`'' \| 'success' \| 'info' \| 'warning' \| 'danger'` | info | +| tag-effect ^(2.7.7) | tag effect | ^[enum]`'' \| 'light' \| 'dark' \| 'plain'` | light | +| aria-label ^(a11y) ^(2.5.0) | same as `aria-label` in native input | ^[string] | — | +| empty-values ^(2.7.0) | empty values of component, [see config-provider](./config-provider.md#empty-values-configurations) | ^[array] | — | +| value-on-clear ^(2.7.0) | clear return value, [see config-provider](./config-provider.md#empty-values-configurations) | ^[string] / ^[number] / ^[boolean] / ^[Function] | — | +| popper-append-to-body ^(deprecated) | whether to append the popper menu to body. If the positioning of the popper is wrong, you can try to set this prop to false | ^[boolean] | false | +| tabindex ^(2.9.0) | tabindex for input | ^[string] / ^[number] | — | ### props @@ -302,6 +303,41 @@ select-v2/custom-width | options | specify which key of node object is used as the node's children | ^[string] | options | | disabled | specify which key of node object is used as the node's disabled | ^[string] | disabled | +### tag-tooltip ^(2.13.3) + +:::tip Fallback Mechanism + +Properties in tag-tooltip follow this priority order: + +1. Explicitly defined fields within the tag-tooltip object. +2. Shared props inherited from el-select-v2 (e.g. effect, popper-class, popper-style, teleported, append-to, popper-options). +3. Default values of the underlying el-tooltip component. + This allows you to override specific tooltip behaviors for tags while maintaining consistency with the Select dropdown by default. + +::: + +:::tip Custom Container Positioning + +When appending the Tooltip to a custom container (via the `append-to` attribute), the container should be configured with `position: relative` or `position: absolute` to ensure accurate positioning. Additionally, you can apply `overflow: hidden` to the container if you need to prevent the Tooltip from overflowing its boundaries. + +::: + +| Attribute | Description | Type | Default | +| ------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| append-to | which element the tooltip CONTENT appends to | ^[CSSSelector] / ^[HTMLElement] | — | +| placement | position of Tooltip | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom | +| fallback-placements | list of possible positions for Tooltip [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom', 'top', 'right', 'left'] | +| effect | Tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | — | +| popper-class | custom class name for Tooltip's popper | ^[string] | — | +| popper-style | custom style for Tooltip's popper | ^[string] / ^[object] | — | +| transition | animation name | ^[string] | — | +| teleported | whether tooltip content is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | — | +| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | — | +| show-after | delay of appearance, in millisecond | ^[number] | — | +| hide-after | delay of disappear, in millisecond | ^[number] | — | +| auto-close | timeout in milliseconds to hide tooltip | ^[number] | — | +| offset | offset of the Tooltip | ^[number] | — | + ### Events | Name | Description | Type | diff --git a/docs/en-US/component/select.md b/docs/en-US/component/select.md index 7a5959eeea..f82a59feeb 100644 --- a/docs/en-US/component/select.md +++ b/docs/en-US/component/select.md @@ -201,60 +201,61 @@ select/custom-label ### Select Attributes -| Name | Description | Type | Default | -| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] / ^[object] / ^[array] | — | -| multiple | whether multiple-select is activated | ^[boolean] | false | -| options ^(2.10.5) | data of the options, the key of `value` and `label` and `disabled` can be customize by `props` | ^[array]`Array<{[key: string]: any}>` | — | -| [props](#props) ^(2.10.5) | configuration options | ^[object] | — | -| disabled | whether Select is disabled | ^[boolean] | false | -| value-key | unique identity key name for value, required when value is an object | ^[string] | value | -| size | size of Input | ^[enum]`'' \| 'large' \| 'default' \| 'small'` | — | -| clearable | whether select can be cleared | ^[boolean] | false | -| collapse-tags | whether to collapse tags to a text when multiple selecting | ^[boolean] | false | -| collapse-tags-tooltip ^(2.3.0) | whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true | ^[boolean] | false | -| multiple-limit | maximum number of options user can select when `multiple` is `true`. No limit when set to 0 | ^[number] | 0 | -| id | native input id input | ^[string] | — | -| name | the name attribute of select input | ^[string] | — | -| effect | tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | light | -| autocomplete | the autocomplete attribute of select input | ^[string] | off | -| placeholder | placeholder, default is 'Select' | ^[string] | — | -| filterable | whether Select is filterable | ^[boolean] | false | -| allow-create | whether creating new items is allowed. To use this, `filterable` must be true | ^[boolean] | false | -| filter-method | custom filter method, the first parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | -| remote | whether options are loaded from server | ^[boolean] | false | -| debounce ^(2.11.7) | debounce delay during remote search, in milliseconds | ^[number] | 300 | -| remote-method | function that gets called when the input value changes. Its parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | -| remote-show-suffix | in remote search method show suffix icon | ^[boolean] | false | -| loading | whether Select is loading data from server | ^[boolean] | false | -| loading-text | displayed text while loading data from server, default is 'Loading' | ^[string] | — | -| no-match-text | displayed text when no data matches the filtering query, you can also use slot `empty`, default is 'No matching data' | ^[string] | — | -| no-data-text | displayed text when there is no options, you can also use slot `empty`, default is 'No data' | ^[string] | — | -| popper-class | custom class name for Select's dropdown and tags' tooltip | ^[string] | '' | -| popper-style ^(2.11.0) | custom style for Select's dropdown and tags' tooltip | ^[string] / ^[object] | — | -| reserve-keyword | when `multiple` and `filterable` is true, whether to reserve current keyword after selecting an option | ^[boolean] | true | -| default-first-option | select first matching option on enter key. Use with `filterable` or `remote` | ^[boolean] | false | -| teleported | whether select dropdown is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | true | -| append-to ^(2.8.4) | which element the select dropdown appends to | ^[CSSSelector] / ^[HTMLElement] | — | -| persistent | when select dropdown is inactive and `persistent` is `false`, select dropdown will be destroyed | ^[boolean] | true | -| automatic-dropdown | for non-filterable Select, this prop decides if the option menu pops up when the input is focused | ^[boolean] | false | -| clear-icon | custom clear icon component | ^[string] / ^[object]`Component` | CircleClose | -| fit-input-width | whether the width of the dropdown is the same as the input | ^[boolean] | false | -| suffix-icon | custom suffix icon component | ^[string] / ^[object]`Component` | ArrowDown | -| tag-type | tag type | ^[enum]`'' \| 'success' \| 'info' \| 'warning' \| 'danger'` | info | -| tag-effect ^(2.7.7) | tag effect | ^[enum]`'' \| 'light' \| 'dark' \| 'plain'` | light | -| validate-event | whether to trigger form validation | ^[boolean] | true | -| offset ^(2.8.8) | offset of the dropdown | ^[number] | 12 | -| show-arrow ^(2.8.8) | whether the dropdown has an arrow | ^[boolean] | true | -| placement ^(2.2.17) | position of dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom-start | -| fallback-placements ^(2.5.6) | list of possible positions for dropdown [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom-start', 'top-start', 'right', 'left'] | -| max-collapse-tags ^(2.3.0) | the max tags number to be shown. To use this, `collapse-tags` must be true | ^[number] | 1 | -| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | {} | -| aria-label ^(a11y) | same as `aria-label` in native input | ^[string] | — | -| empty-values ^(2.7.0) | empty values of component, [see config-provider](./config-provider.md#empty-values-configurations) | ^[array] | — | -| value-on-clear ^(2.7.0) | clear return value, [see config-provider](./config-provider.md#empty-values-configurations) | ^[string] / ^[number] / ^[boolean] / ^[Function] | — | -| suffix-transition ^(deprecated) | animation when dropdown appears/disappears icon | ^[boolean] | true | -| tabindex ^(2.9.0) | tabindex for input | ^[string] / ^[number] | — | +| Name | Description | Type | Default | +| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | +| model-value / v-model | binding value | ^[string] / ^[number] / ^[boolean] / ^[object] / ^[array] | — | +| multiple | whether multiple-select is activated | ^[boolean] | false | +| options ^(2.10.5) | data of the options, the key of `value` and `label` and `disabled` can be customize by `props` | ^[array]`Array<{[key: string]: any}>` | — | +| [props](#props) ^(2.10.5) | configuration options | ^[object] | — | +| disabled | whether Select is disabled | ^[boolean] | false | +| value-key | unique identity key name for value, required when value is an object | ^[string] | value | +| size | size of Input | ^[enum]`'' \| 'large' \| 'default' \| 'small'` | — | +| clearable | whether select can be cleared | ^[boolean] | false | +| collapse-tags | whether to collapse tags to a text when multiple selecting | ^[boolean] | false | +| collapse-tags-tooltip ^(2.3.0) | whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true | ^[boolean] | false | +| [tag-tooltip](#tag-tooltip) ^(2.13.3) | configuration object for the collapse-tags tooltip. To use this, `collapse-tags` and `collapse-tags-tooltip` must be true | ^[object]`TagTooltipProps` | {} | +| multiple-limit | maximum number of options user can select when `multiple` is `true`. No limit when set to 0 | ^[number] | 0 | +| id | native input id input | ^[string] | — | +| name | the name attribute of select input | ^[string] | — | +| effect | tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | light | +| autocomplete | the autocomplete attribute of select input | ^[string] | off | +| placeholder | placeholder, default is 'Select' | ^[string] | — | +| filterable | whether Select is filterable | ^[boolean] | false | +| allow-create | whether creating new items is allowed. To use this, `filterable` must be true | ^[boolean] | false | +| filter-method | custom filter method, the first parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | +| remote | whether options are loaded from server | ^[boolean] | false | +| debounce ^(2.11.7) | debounce delay during remote search, in milliseconds | ^[number] | 300 | +| remote-method | function that gets called when the input value changes. Its parameter is the current input value. To use this, `filterable` must be true | ^[Function]`(query: string) => void` | — | +| remote-show-suffix | in remote search method show suffix icon | ^[boolean] | false | +| loading | whether Select is loading data from server | ^[boolean] | false | +| loading-text | displayed text while loading data from server, default is 'Loading' | ^[string] | — | +| no-match-text | displayed text when no data matches the filtering query, you can also use slot `empty`, default is 'No matching data' | ^[string] | — | +| no-data-text | displayed text when there is no options, you can also use slot `empty`, default is 'No data' | ^[string] | — | +| popper-class | custom class name for Select's dropdown and tags' tooltip | ^[string] | '' | +| popper-style ^(2.11.0) | custom style for Select's dropdown and tags' tooltip | ^[string] / ^[object] | — | +| reserve-keyword | when `multiple` and `filterable` is true, whether to reserve current keyword after selecting an option | ^[boolean] | true | +| default-first-option | select first matching option on enter key. Use with `filterable` or `remote` | ^[boolean] | false | +| teleported | whether select dropdown is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | true | +| append-to ^(2.8.4) | which element the select dropdown appends to | ^[CSSSelector] / ^[HTMLElement] | — | +| persistent | when select dropdown is inactive and `persistent` is `false`, select dropdown will be destroyed | ^[boolean] | true | +| automatic-dropdown | for non-filterable Select, this prop decides if the option menu pops up when the input is focused | ^[boolean] | false | +| clear-icon | custom clear icon component | ^[string] / ^[object]`Component` | CircleClose | +| fit-input-width | whether the width of the dropdown is the same as the input | ^[boolean] | false | +| suffix-icon | custom suffix icon component | ^[string] / ^[object]`Component` | ArrowDown | +| tag-type | tag type | ^[enum]`'' \| 'success' \| 'info' \| 'warning' \| 'danger'` | info | +| tag-effect ^(2.7.7) | tag effect | ^[enum]`'' \| 'light' \| 'dark' \| 'plain'` | light | +| validate-event | whether to trigger form validation | ^[boolean] | true | +| offset ^(2.8.8) | offset of the dropdown | ^[number] | 12 | +| show-arrow ^(2.8.8) | whether the dropdown has an arrow | ^[boolean] | true | +| placement ^(2.2.17) | position of dropdown | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom-start | +| fallback-placements ^(2.5.6) | list of possible positions for dropdown [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom-start', 'top-start', 'right', 'left'] | +| max-collapse-tags ^(2.3.0) | the max tags number to be shown. To use this, `collapse-tags` must be true | ^[number] | 1 | +| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | {} | +| aria-label ^(a11y) | same as `aria-label` in native input | ^[string] | — | +| empty-values ^(2.7.0) | empty values of component, [see config-provider](./config-provider.md#empty-values-configurations) | ^[array] | — | +| value-on-clear ^(2.7.0) | clear return value, [see config-provider](./config-provider.md#empty-values-configurations) | ^[string] / ^[number] / ^[boolean] / ^[Function] | — | +| suffix-transition ^(deprecated) | animation when dropdown appears/disappears icon | ^[boolean] | true | +| tabindex ^(2.9.0) | tabindex for input | ^[string] / ^[number] | — | :::warning @@ -271,6 +272,41 @@ select/custom-label | options ^(2.11.0) | specify which key of node object is used as the node's children | ^[string] | options | | disabled | specify which key of node object is used as the node's disabled | ^[string] | disabled | +### tag-tooltip ^(2.13.3) + +:::tip Fallback Mechanism + +Properties in tag-tooltip follow this priority order: + +1. Explicitly defined fields within the tag-tooltip object. +2. Shared props inherited from el-select (e.g. effect, popper-class, popper-style, teleported, append-to, popper-options). +3. Default values of the underlying el-tooltip component. + This allows you to override specific tooltip behaviors for tags while maintaining consistency with the Select dropdown by default. + +::: + +:::tip Custom Container Positioning + +When appending the Tooltip to a custom container (via the `append-to` attribute), the container should be configured with `position: relative` or `position: absolute` to ensure accurate positioning. Additionally, you can apply `overflow: hidden` to the container if you need to prevent the Tooltip from overflowing its boundaries. + +::: + +| Attribute | Description | Type | Default | +| ------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| append-to | which element the tooltip CONTENT appends to | ^[CSSSelector] / ^[HTMLElement] | — | +| placement | position of Tooltip | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | bottom | +| fallback-placements | list of possible positions for Tooltip [popper.js](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements) | ^[array]`Placement[]` | ['bottom', 'top', 'right', 'left'] | +| effect | Tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | — | +| popper-class | custom class name for Tooltip's popper | ^[string] | — | +| popper-style | custom style for Tooltip's popper | ^[string] / ^[object] | — | +| transition | animation name | ^[string] | — | +| teleported | whether tooltip content is teleported, if `true` it will be teleported to where `append-to` sets | ^[boolean] | — | +| popper-options | [popper.js](https://popper.js.org/docs/v2/) parameters | ^[object]refer to [popper.js](https://popper.js.org/docs/v2/) doc | — | +| show-after | delay of appearance, in millisecond | ^[number] | — | +| hide-after | delay of disappear, in millisecond | ^[number] | — | +| auto-close | timeout in milliseconds to hide tooltip | ^[number] | — | +| offset | offset of the Tooltip | ^[number] | — | + ### Select Events | Name | Description | Type | diff --git a/packages/components/select-v2/__tests__/select.test.ts b/packages/components/select-v2/__tests__/select.test.ts index 3b8b4324c2..d747f65bbb 100644 --- a/packages/components/select-v2/__tests__/select.test.ts +++ b/packages/components/select-v2/__tests__/select.test.ts @@ -68,6 +68,7 @@ interface SelectProps { multiple?: boolean collapseTags?: boolean collapseTagsTooltip?: boolean + tagTooltip?: Record maxCollapseTags?: number filterable?: boolean remote?: boolean @@ -136,6 +137,7 @@ const createSelect = ( :multiple="multiple" :collapseTags="collapseTags" :collapseTagsTooltip="collapseTagsTooltip" + :tag-tooltip="tagTooltip" :max-collapse-tags="maxCollapseTags" :filterable="filterable" :multiple-limit="multipleLimit" @@ -189,6 +191,7 @@ const createSelect = ( multiple: false, collapseTags: false, collapseTagsTooltip: false, + tagTooltip: undefined, maxCollapseTags: 1, remote: false, filterable: false, @@ -916,6 +919,43 @@ describe('Select', () => { }) expect(tags.length).toBe(4) }) + + it('use tag-tooltip', async () => { + const appendTarget = document.createElement('div') + appendTarget.className = 'append-target' + document.body.appendChild(appendTarget) + const wrapper = createSelect({ + data: () => { + return { + multiple: true, + collapseTags: true, + collapseTagsTooltip: true, + tagTooltip: { appendTo: '.append-target' }, + value: [], + } + }, + }) + await nextTick() + const options = getOptions() + options[0].click() + await nextTick() + options[1].click() + await nextTick() + options[2].click() + await nextTick() + + const select = wrapper.findComponent(Select) + const tagTooltip = select.findComponent({ ref: 'tagTooltipRef' }) + expect(tagTooltip.props('appendTo')).toBe('.append-target') + + const triggerWrappers = wrapper.findAll('.el-tooltip__trigger') + expect(triggerWrappers[0]).toBeDefined() + const tags = wrapper.findAll('.el-tag').filter((item) => { + return !hasClass(item.element, 'in-tooltip') + }) + expect(tags.length).toBe(2) + expect(tags[1].element.textContent.trim()).toBe('+ 2') + }) }) describe('manually set modelValue', () => { diff --git a/packages/components/select-v2/src/defaults.ts b/packages/components/select-v2/src/defaults.ts index 9b28f71c41..938b520fd2 100644 --- a/packages/components/select-v2/src/defaults.ts +++ b/packages/components/select-v2/src/defaults.ts @@ -21,13 +21,36 @@ import type SelectV2 from './select.vue' import type { Option, OptionType } from './select.types' import type { Props } from './useProps' import type { EmitFn } from '@element-plus/utils/vue/typescript' -import type { ExtractPropTypes, ExtractPublicPropTypes } from 'vue' +import type { + CSSProperties, + ExtractPropTypes, + ExtractPublicPropTypes, +} from 'vue' import type { Options, Placement, PopperEffect, } from '@element-plus/components/popper' +/** + * @description Tag tooltip configuration interface + */ +export interface TagTooltipProps { + appendTo?: string | HTMLElement + placement?: Placement + fallbackPlacements?: Placement[] + effect?: PopperEffect + popperClass?: string + popperStyle?: string | CSSProperties + transition?: string + teleported?: boolean + popperOptions?: Partial + showAfter?: number + hideAfter?: number + autoClose?: number + offset?: number +} + export const selectV2Props = buildProps({ /** * @description whether creating new items is allowed. To use this, `filterable` must be true @@ -70,6 +93,13 @@ export const selectV2Props = buildProps({ * @description whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true */ collapseTagsTooltip: Boolean, + /** + * @description configuration object for the collapse-tags tooltip. To use this, `collapse-tags` and `collapse-tags-tooltip` must be true + */ + tagTooltip: { + type: definePropType(Object), + default: () => ({}), + }, /** * @description The max tags number to be shown. To use this, `collapse-tags` must be true */ diff --git a/packages/components/select-v2/src/select.vue b/packages/components/select-v2/src/select.vue index 77129bda36..1b25080774 100644 --- a/packages/components/select-v2/src/select.vue +++ b/packages/components/select-v2/src/select.vue @@ -92,16 +92,31 @@