From b9a55d634bdb62f4bcc533340dd8ef2527acbc8d Mon Sep 17 00:00:00 2001 From: Milen Karmidzhanov Date: Thu, 4 Jun 2026 11:18:12 +0300 Subject: [PATCH 1/5] feat(ui5-comobobox, ui5-multi-combobox): add custom items --- packages/main/cypress/specs/ComboBox.cy.tsx | 217 +++++++++++++ .../main/cypress/specs/MultiComboBox.cy.tsx | 292 ++++++++++++++++++ packages/main/src/ComboBox.ts | 1 + packages/main/src/ComboBoxItemCustom.ts | 82 +++++ .../main/src/ComboBoxItemCustomTemplate.tsx | 10 + packages/main/src/MultiComboBox.ts | 1 + packages/main/src/MultiComboBoxItemCustom.ts | 89 ++++++ .../src/MultiComboBoxItemCustomTemplate.tsx | 22 ++ .../main/src/themes/ComboBoxItemCustom.css | 14 + .../src/themes/MultiComboBoxItemCustom.css | 19 ++ packages/main/test/pages/ComboBox.html | 53 ++++ .../main/ComboBox/CustomItems/CustomItems.md | 4 + .../main/ComboBox/CustomItems/main.js | 2 + .../main/ComboBox/CustomItems/sample.html | 34 ++ .../MultiComboBox/CustomItems/CustomItems.md | 4 + .../main/MultiComboBox/CustomItems/main.js | 2 + .../MultiComboBox/CustomItems/sample.html | 34 ++ 17 files changed, 880 insertions(+) create mode 100644 packages/main/src/ComboBoxItemCustom.ts create mode 100644 packages/main/src/ComboBoxItemCustomTemplate.tsx create mode 100644 packages/main/src/MultiComboBoxItemCustom.ts create mode 100644 packages/main/src/MultiComboBoxItemCustomTemplate.tsx create mode 100644 packages/main/src/themes/ComboBoxItemCustom.css create mode 100644 packages/main/src/themes/MultiComboBoxItemCustom.css create mode 100644 packages/website/docs/_samples/main/ComboBox/CustomItems/CustomItems.md create mode 100644 packages/website/docs/_samples/main/ComboBox/CustomItems/main.js create mode 100644 packages/website/docs/_samples/main/ComboBox/CustomItems/sample.html create mode 100644 packages/website/docs/_samples/main/MultiComboBox/CustomItems/CustomItems.md create mode 100644 packages/website/docs/_samples/main/MultiComboBox/CustomItems/main.js create mode 100644 packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.html diff --git a/packages/main/cypress/specs/ComboBox.cy.tsx b/packages/main/cypress/specs/ComboBox.cy.tsx index 0cd2803c939b..92f04e10217a 100644 --- a/packages/main/cypress/specs/ComboBox.cy.tsx +++ b/packages/main/cypress/specs/ComboBox.cy.tsx @@ -1,6 +1,7 @@ import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import ComboBox from "../../src/ComboBox.js"; import ComboBoxItem from "../../src/ComboBoxItem.js"; +import ComboBoxItemCustom from "../../src/ComboBoxItemCustom.js"; import ComboBoxItemGroup from "../../src/ComboBoxItemGroup.js"; import ResponsivePopover from "../../src/ResponsivePopover.js"; import Link from "../../src/Link.js"; @@ -3992,3 +3993,219 @@ describe("Highlighting", () => { .should("contain.html", "AFR"); }); }); + +describe("ComboBoxItemCustom - Rendering", () => { + it("should render custom content correctly", () => { + cy.mount( + + + 🇩🇪 Germany + + + 🇫🇷 France + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-cbi-custom]").eq(0).shadow().find("li").should("contain.text", "🇩🇪 Germany"); + cy.get("[ui5-cbi-custom]").eq(1).shadow().find("li").should("contain.text", "🇫🇷 France"); + }); + + it("should mix regular and custom items", () => { + cy.mount( + + + + Custom Item + + + ); + + cy.get("[ui5-combobox]") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-cb-item]").should("have.length", 1); + cy.get("[ui5-cbi-custom]").should("have.length", 1); + }); + + it("should have role='option'", () => { + cy.mount( + + Test Item + + ); + + cy.get("[ui5-combobox]") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-cbi-custom]").shadow().find("li").should("have.attr", "role", "option"); + }); +}); + +describe("ComboBoxItemCustom - Filtering", () => { + it("should filter custom items by text property", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .realClick(); + + cy.get("@combobox").realPress("G"); + + cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "_isVisible", true); + cy.get("[ui5-cbi-custom]").eq(1).should("not.have.prop", "_isVisible", true); + cy.get("[ui5-cbi-custom]").eq(2).should("not.have.prop", "_isVisible", true); + }); + + it("should filter mixed regular and custom items", () => { + cy.mount( + + + 🇩🇪 Germany + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .realClick(); + + cy.get("@combobox").realPress("G"); + + cy.get("[ui5-cb-item]").eq(0).should("not.have.prop", "_isVisible", true); + cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "_isVisible", true); + cy.get("[ui5-cb-item]").eq(1).should("not.have.prop", "_isVisible", true); + }); +}); + +describe("ComboBoxItemCustom - Selection", () => { + it("should select custom item on click", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-cbi-custom]").eq(0).shadow().find("li").realClick(); + + cy.get("@combobox").should("have.prop", "value", "Germany"); + }); + + it("should select custom item with Enter key", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .realClick(); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("Enter"); + + cy.get("@combobox").should("have.prop", "value", "Germany"); + }); + + it("should work with value property for programmatic selection", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-combobox]").should("have.prop", "value", "France"); + cy.get("[ui5-combobox]").should("have.prop", "selectedValue", "FR"); + }); +}); + +describe("ComboBoxItemCustom - Navigation", () => { + it("should navigate through custom items with arrow keys", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .realClick(); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("[ui5-cbi-custom]").eq(1).should("have.prop", "focused", true); + + cy.get("@combobox").realPress("ArrowUp"); + cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); + }); + + it("should navigate through mixed items", () => { + cy.mount( + + + 🇩🇪 Germany + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .realClick(); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("[ui5-cb-item]").eq(0).should("have.prop", "focused", true); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("[ui5-cb-item]").eq(1).should("have.prop", "focused", true); + }); +}); + +describe("ComboBoxItemCustom - Accessibility", () => { + it("should have correct tabindex", () => { + cy.mount( + + Test Item + + ); + + cy.get("[ui5-combobox]") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-cbi-custom]").shadow().find("li").should("not.have.attr", "tabindex", "0"); + }); +}); diff --git a/packages/main/cypress/specs/MultiComboBox.cy.tsx b/packages/main/cypress/specs/MultiComboBox.cy.tsx index 1ebf822ad04d..884ec158fbeb 100644 --- a/packages/main/cypress/specs/MultiComboBox.cy.tsx +++ b/packages/main/cypress/specs/MultiComboBox.cy.tsx @@ -1,5 +1,6 @@ import MultiComboBox from "../../src/MultiComboBox.js"; import MultiComboBoxItem from "../../src/MultiComboBoxItem.js"; +import MultiComboBoxItemCustom from "../../src/MultiComboBoxItemCustom.js"; import MultiComboBoxItemGroup from "../../src/MultiComboBoxItemGroup.js"; import ResponsivePopover from "../../src/ResponsivePopover.js"; import Button from "../../src/Button.js"; @@ -5143,3 +5144,294 @@ describe("Validation inside a form", () => { .should("have.been.calledOnce"); }); }); + +describe("MultiComboBoxItemCustom - Rendering", () => { + it("should render custom content correctly", () => { + cy.mount( + + + 🇩🇪 Germany + + + 🇫🇷 France + + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).shadow().find(".ui5-li-content").should("contain.text", "🇩🇪 Germany"); + cy.get("[ui5-mcbi-custom]").eq(1).shadow().find(".ui5-li-content").should("contain.text", "🇫🇷 France"); + }); + + it("should render checkbox for custom items", () => { + cy.mount( + + 🇩🇪 Germany + + ); + + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcbi-custom]").shadow().find("[ui5-checkbox]").should("exist"); + }); + + it("should mix regular and custom items", () => { + cy.mount( + + + + Custom Item + + + ); + + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcb-item]").should("have.length", 1); + cy.get("[ui5-mcbi-custom]").should("have.length", 1); + }); +}); + +describe("MultiComboBoxItemCustom - Filtering", () => { + it("should filter custom items by text property", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .realClick(); + + cy.get("@multiCombobox").realPress("G"); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "_isVisible", true); + cy.get("[ui5-mcbi-custom]").eq(1).should("not.have.prop", "_isVisible", true); + cy.get("[ui5-mcbi-custom]").eq(2).should("not.have.prop", "_isVisible", true); + }); + + it("should filter mixed regular and custom items", () => { + cy.mount( + + + 🇩🇪 Germany + + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .realClick(); + + cy.get("@multiCombobox").realPress("G"); + + cy.get("[ui5-mcb-item]").eq(0).should("not.have.prop", "_isVisible", true); + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "_isVisible", true); + cy.get("[ui5-mcb-item]").eq(1).should("not.have.prop", "_isVisible", true); + }); +}); + +describe("MultiComboBoxItemCustom - Selection", () => { + it("should select custom item via checkbox click", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).shadow().find("[ui5-checkbox]").realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", true); + cy.get("@multiCombobox").shadow().find("[ui5-token]").should("have.length", 1); + }); + + it("should select multiple custom items", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).shadow().find("[ui5-checkbox]").realClick(); + cy.get("[ui5-mcbi-custom]").eq(1).shadow().find("[ui5-checkbox]").realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", true); + cy.get("[ui5-mcbi-custom]").eq(1).should("have.prop", "selected", true); + cy.get("@multiCombobox").shadow().find("[ui5-token]").should("have.length", 2); + }); + + it("should work with selectedValues property", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", true); + cy.get("[ui5-mcbi-custom]").eq(1).should("have.prop", "selected", true); + cy.get("[ui5-mcbi-custom]").eq(2).should("have.prop", "selected", false); + + cy.get("[ui5-multi-combobox]").shadow().find("[ui5-token]").should("have.length", 2); + }); +}); + +describe("MultiComboBoxItemCustom - Tokens", () => { + it("should display token with text property", () => { + cy.mount( + + 🇩🇪 Germany + + ); + + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-token]") + .should("have.length", 1) + .and("have.prop", "text", "Germany"); + }); + + it("should display tokens for multiple selected items", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .shadow() + .find("[ui5-token]") + .should("have.length", 2); + + cy.get("@multiCombobox").shadow().find("[ui5-token]").eq(0).should("have.prop", "text", "Germany"); + cy.get("@multiCombobox").shadow().find("[ui5-token]").eq(1).should("have.prop", "text", "France"); + }); + + it("should remove selection when token is deleted", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + + ); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", true); + + cy.get("[ui5-multi-combobox]") + .shadow() + .find("[ui5-token]") + .eq(0) + .shadow() + .find(".ui5-token-icon") + .realClick(); + + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", false); + cy.get("[ui5-multi-combobox]").shadow().find("[ui5-token]").should("have.length", 0); + }); +}); + +describe("MultiComboBoxItemCustom - Navigation", () => { + it("should navigate through custom items with arrow keys", () => { + cy.mount( + + 🇩🇪 Germany + 🇫🇷 France + 🇪🇸 Spain + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .realClick(); + + cy.get("@multiCombobox").realPress("ArrowDown"); + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + + cy.get("@multiCombobox").realPress("ArrowDown"); + cy.get("[ui5-mcbi-custom]").eq(1).should("have.prop", "focused", true); + + cy.get("@multiCombobox").realPress("ArrowUp"); + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + }); + + it("should navigate through mixed items", () => { + cy.mount( + + + 🇩🇪 Germany + + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .realClick(); + + cy.get("@multiCombobox").realPress("ArrowDown"); + cy.get("[ui5-mcb-item]").eq(0).should("have.prop", "focused", true); + + cy.get("@multiCombobox").realPress("ArrowDown"); + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + + cy.get("@multiCombobox").realPress("ArrowDown"); + cy.get("[ui5-mcb-item]").eq(1).should("have.prop", "focused", true); + }); +}); + +describe("MultiComboBoxItemCustom - Mixed Selection", () => { + it("should select both regular and custom items", () => { + cy.mount( + + + 🇩🇪 Germany + + + ); + + cy.get("[ui5-multi-combobox]") + .as("multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("[ui5-mcb-item]").eq(0).shadow().find("[ui5-checkbox]").realClick(); + cy.get("[ui5-mcbi-custom]").eq(0).shadow().find("[ui5-checkbox]").realClick(); + + cy.get("[ui5-mcb-item]").eq(0).should("have.prop", "selected", true); + cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", true); + + cy.get("@multiCombobox").shadow().find("[ui5-token]").should("have.length", 2); + }); +}); diff --git a/packages/main/src/ComboBox.ts b/packages/main/src/ComboBox.ts index c7bc268c62c0..f71adbedc173 100644 --- a/packages/main/src/ComboBox.ts +++ b/packages/main/src/ComboBox.ts @@ -79,6 +79,7 @@ import SuggestionsCss from "./generated/themes/Suggestions.css.js"; import "./ComboBoxItem.js"; import type ComboBoxItem from "./ComboBoxItem.js"; +import "./ComboBoxItemCustom.js"; import type Popover from "./Popover.js"; import type ResponsivePopover from "./ResponsivePopover.js"; import type List from "./List.js"; diff --git a/packages/main/src/ComboBoxItemCustom.ts b/packages/main/src/ComboBoxItemCustom.ts new file mode 100644 index 000000000000..ad1a5cd85f56 --- /dev/null +++ b/packages/main/src/ComboBoxItemCustom.ts @@ -0,0 +1,82 @@ +import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; +import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js"; +import type { IComboBoxItem } from "./ComboBox.js"; +import ListItemBase from "./ListItemBase.js"; +import ComboBoxItemCustomTemplate from "./ComboBoxItemCustomTemplate.js"; +import styles from "./generated/themes/ComboBoxItemCustom.css.js"; +import type { DefaultSlot } from "@ui5/webcomponents-base/dist/UI5Element.js"; + +/** + * @class + * The `ui5-cbi-custom` is type of combobox item, + * that can be used to place combobox items with custom content in the combobox. + * The text property is considered for filtering and autocomplete. + * + * @constructor + * @extends ListItemBase + * @implements {IComboBoxItem} + * @public + * @since 2.24.0 + */ +@customElement({ + tag: "ui5-cbi-custom", + template: ComboBoxItemCustomTemplate, + styles: [ + ListItemBase.styles, + styles, + ], +}) +class ComboBoxItemCustom extends ListItemBase implements IComboBoxItem { + eventDetails!: ListItemBase["eventDetails"]; + + /** + * Defines the text of the component. + * Used for filtering, autocomplete, and mobile rendering. + * @default undefined + * @public + * @since 2.24.0 + */ + @property() + text?: string; + + /** + * Defines the value of the component. + * Used for programmatic selection via selectedValue property. + * @default undefined + * @public + * @since 2.24.0 + */ + @property() + value?: string; + + /** + * Indicates whether the item is filtered. + * @private + */ + @property({ type: Boolean, noAttribute: true }) + _isVisible = false; + + /** + * Indicates whether the item is focused. + * @protected + */ + @property({ type: Boolean }) + focused = false; + + /** + * Defines the content of the component. + * @public + * @since 2.24.0 + */ + @slot({ type: Node, "default": true, invalidateOnChildChange: true }) + content!: DefaultSlot; + + get _effectiveTabIndex() { + return -1; + } +} + +ComboBoxItemCustom.define(); + +export default ComboBoxItemCustom; diff --git a/packages/main/src/ComboBoxItemCustomTemplate.tsx b/packages/main/src/ComboBoxItemCustomTemplate.tsx new file mode 100644 index 000000000000..5c8e2999889c --- /dev/null +++ b/packages/main/src/ComboBoxItemCustomTemplate.tsx @@ -0,0 +1,10 @@ +import ListItemBaseTemplate from "./ListItemBaseTemplate.js"; +import type ComboBoxItemCustom from "./ComboBoxItemCustom.js"; + +export default function ComboBoxItemCustomTemplate(this: ComboBoxItemCustom) { + return ListItemBaseTemplate.call(this, { listItemContent }, { role: "option" }); +} + +function listItemContent(this: ComboBoxItemCustom) { + return ; +} diff --git a/packages/main/src/MultiComboBox.ts b/packages/main/src/MultiComboBox.ts index 085142308936..e0e250a8421b 100644 --- a/packages/main/src/MultiComboBox.ts +++ b/packages/main/src/MultiComboBox.ts @@ -59,6 +59,7 @@ import arraysAreEqual from "@ui5/webcomponents-base/dist/util/arraysAreEqual.js" import { submitForm } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js"; import MultiComboBoxItem, { isInstanceOfMultiComboBoxItem } from "./MultiComboBoxItem.js"; +import "./MultiComboBoxItemCustom.js"; import MultiComboBoxItemGroup, { isInstanceOfMultiComboBoxItemGroup } from "./MultiComboBoxItemGroup.js"; import ListItemGroup from "./ListItemGroup.js"; import Tokenizer, { getTokensCountText } from "./Tokenizer.js"; diff --git a/packages/main/src/MultiComboBoxItemCustom.ts b/packages/main/src/MultiComboBoxItemCustom.ts new file mode 100644 index 000000000000..1a5eee698dd0 --- /dev/null +++ b/packages/main/src/MultiComboBoxItemCustom.ts @@ -0,0 +1,89 @@ +import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; +import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js"; +import { + property, + eventStrict as event, +} from "@ui5/webcomponents-base/dist/decorators.js"; +import ComboBoxItemCustom from "./ComboBoxItemCustom.js"; +import CheckBox from "./CheckBox.js"; +import type { IMultiComboBoxItem } from "./MultiComboBox.js"; +import { + ARIA_LABEL_LIST_ITEM_CHECKBOX, +} from "./generated/i18n/i18n-defaults.js"; +import styles from "./generated/themes/MultiComboBoxItemCustom.css.js"; +import MultiComboBoxItemCustomTemplate from "./MultiComboBoxItemCustomTemplate.js"; +import type { SelectionRequestEventDetail } from "./ListItem.js"; +import type { AriaRole } from "@ui5/webcomponents-base"; + +/** + * @class + * The `ui5-mcbi-custom` is type of multi-combobox item, + * that can be used to place multi-combobox items with custom content. + * The text property is considered for filtering and token display. + * + * @constructor + * @extends ComboBoxItemCustom + * @implements {IMultiComboBoxItem} + * @public + * @since 2.24.0 + */ +@customElement({ + tag: "ui5-mcbi-custom", + template: MultiComboBoxItemCustomTemplate, + styles: [ComboBoxItemCustom.styles, styles], + dependencies: [...ComboBoxItemCustom.dependencies, CheckBox], +}) + +@event("selection-requested", { + bubbles: true, +}) +class MultiComboBoxItemCustom extends ComboBoxItemCustom implements IMultiComboBoxItem { + eventDetails!: ComboBoxItemCustom["eventDetails"] & { + "selection-requested": SelectionRequestEventDetail, + } + + /** + * Defines the selected state of the component. + * @default false + * @public + * @deprecated Set the `value` property on items and use the `selectedValues` property on the parent `ui5-multi-combobox` instead for programmatic selection. + */ + @property({ type: Boolean }) + selected = false; + + /** + * @private + */ + @property({ type: Boolean, noAttribute: true }) + _readonly = false; + + @i18n("@ui5/webcomponents") + static i18nBundle: I18nBundle; + + get isMultiComboBoxItem() { + return true; + } + + _onclick(e: MouseEvent) { + if ((e.target as HTMLElement)?.hasAttribute("ui5-checkbox")) { + return this.fireDecoratorEvent("selection-requested", { item: this, selected: (e.target as CheckBox).checked, selectionComponentPressed: true }); + } + + super._onclick(e); + } + + get _accessibleName() { + return MultiComboBoxItemCustom.i18nBundle.getText(ARIA_LABEL_LIST_ITEM_CHECKBOX); + } + + get checkBoxAccInfo() { + return { + role: "presentation" as AriaRole, + }; + } +} + +MultiComboBoxItemCustom.define(); + +export default MultiComboBoxItemCustom; diff --git a/packages/main/src/MultiComboBoxItemCustomTemplate.tsx b/packages/main/src/MultiComboBoxItemCustomTemplate.tsx new file mode 100644 index 000000000000..f6acf5bd381c --- /dev/null +++ b/packages/main/src/MultiComboBoxItemCustomTemplate.tsx @@ -0,0 +1,22 @@ +import CheckBox from "./CheckBox.js"; +import ListItemBaseTemplate from "./ListItemBaseTemplate.js"; +import type MultiComboBoxItemCustom from "./MultiComboBoxItemCustom.js"; + +export default function MultiComboBoxItemCustomTemplate(this: MultiComboBoxItemCustom) { + return ListItemBaseTemplate.call(this, { listItemContent }, { role: "option" }); +} + +function listItemContent(this: MultiComboBoxItemCustom) { + return ( + <> + +
+ +
+ + ); +} diff --git a/packages/main/src/themes/ComboBoxItemCustom.css b/packages/main/src/themes/ComboBoxItemCustom.css new file mode 100644 index 000000000000..06466771c5e8 --- /dev/null +++ b/packages/main/src/themes/ComboBoxItemCustom.css @@ -0,0 +1,14 @@ +:host([ui5-cbi-custom]) { + height: auto; + min-height: var(--_ui5_list_item_base_height); +} + +:host([ui5-cbi-custom]) .ui5-li-root { + min-height: var(--_ui5_list_item_base_height); +} + +:host([ui5-cbi-custom]) .ui5-li-content { + padding-bottom: .5rem; + padding-top: .5rem; + box-sizing: border-box; +} diff --git a/packages/main/src/themes/MultiComboBoxItemCustom.css b/packages/main/src/themes/MultiComboBoxItemCustom.css new file mode 100644 index 000000000000..7e6eb383c5ad --- /dev/null +++ b/packages/main/src/themes/MultiComboBoxItemCustom.css @@ -0,0 +1,19 @@ +:host([ui5-mcbi-custom]) { + height: auto; + min-height: var(--_ui5_list_item_base_height); +} + +:host([ui5-mcbi-custom]) .ui5-li-root { + padding-inline-start: 0; + min-height: var(--_ui5_list_item_base_height); +} + +:host([ui5-mcbi-custom]) .ui5-li-content { + padding-bottom: .5rem; + padding-top: .5rem; + box-sizing: border-box; +} + +:host([ui5-mcbi-custom]) [ui5-checkbox] { + overflow: visible; +} diff --git a/packages/main/test/pages/ComboBox.html b/packages/main/test/pages/ComboBox.html index 0d2e49ee54cf..e655361591a8 100644 --- a/packages/main/test/pages/ComboBox.html +++ b/packages/main/test/pages/ComboBox.html @@ -671,6 +671,59 @@

Dialog Header Title from Label

+
+

ComboBox with Custom Items

+ Custom items with icons/emojis: +
+
+ + + 🇩🇪Germany + + + 🇫🇷France + + + 🇪🇸Spain + + + 🇮🇹Italy + + + 🇬🇧United Kingdom + + +
+ Selected value: +
+ Selected selectedValue: + + +
+ +
+

ComboBox with Mixed Items

+ Regular items mixed with custom items: +
+
+ + + + ⭐ Custom Item with Icon + + + + 🔷 Another Custom Item + + +
+ diff --git a/packages/website/docs/_samples/main/ComboBox/CustomItems/CustomItems.md b/packages/website/docs/_samples/main/ComboBox/CustomItems/CustomItems.md new file mode 100644 index 000000000000..17798ecc59ab --- /dev/null +++ b/packages/website/docs/_samples/main/ComboBox/CustomItems/CustomItems.md @@ -0,0 +1,4 @@ +import html from '!!raw-loader!./sample.html'; +import js from '!!raw-loader!./main.js'; + + diff --git a/packages/website/docs/_samples/main/ComboBox/CustomItems/main.js b/packages/website/docs/_samples/main/ComboBox/CustomItems/main.js new file mode 100644 index 000000000000..77f0d920c858 --- /dev/null +++ b/packages/website/docs/_samples/main/ComboBox/CustomItems/main.js @@ -0,0 +1,2 @@ +import "@ui5/webcomponents/dist/ComboBox.js"; +import "@ui5/webcomponents/dist/ComboBoxItemCustom.js"; diff --git a/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.html b/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.html new file mode 100644 index 000000000000..eaa41f1a5b37 --- /dev/null +++ b/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.html @@ -0,0 +1,34 @@ + + + + + + + ComboBox Custom Items + + + + + + + 🇩🇪Germany + + + 🇫🇷France + + + 🇪🇸Spain + + + 🇮🇹Italy + + + 🇬🇧United Kingdom + + + + + + + + diff --git a/packages/website/docs/_samples/main/MultiComboBox/CustomItems/CustomItems.md b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/CustomItems.md new file mode 100644 index 000000000000..17798ecc59ab --- /dev/null +++ b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/CustomItems.md @@ -0,0 +1,4 @@ +import html from '!!raw-loader!./sample.html'; +import js from '!!raw-loader!./main.js'; + + diff --git a/packages/website/docs/_samples/main/MultiComboBox/CustomItems/main.js b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/main.js new file mode 100644 index 000000000000..318a11a8cff2 --- /dev/null +++ b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/main.js @@ -0,0 +1,2 @@ +import "@ui5/webcomponents/dist/MultiComboBox.js"; +import "@ui5/webcomponents/dist/MultiComboBoxItemCustom.js"; diff --git a/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.html b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.html new file mode 100644 index 000000000000..453020238700 --- /dev/null +++ b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.html @@ -0,0 +1,34 @@ + + + + + + + MultiComboBox Custom Items + + + + + + + 🇩🇪Germany + + + 🇫🇷France + + + 🇪🇸Spain + + + 🇮🇹Italy + + + 🇬🇧United Kingdom + + + + + + + + From 983f1f5c7ca44d3f1d8412a7369ab259d180712e Mon Sep 17 00:00:00 2001 From: Milen Karmidzhanov Date: Thu, 4 Jun 2026 12:00:23 +0300 Subject: [PATCH 2/5] feat(ui5-comobobox, ui5-multi-combobox): add custom items --- packages/main/cypress/specs/ComboBox.cy.tsx | 20 +++--- .../main/cypress/specs/MultiComboBox.cy.tsx | 56 +++++++++++---- .../main/ComboBox/CustomItems/sample.tsx | 63 +++++++++++++++++ .../main/MultiComboBox/CustomItems/sample.tsx | 68 +++++++++++++++++++ 4 files changed, 184 insertions(+), 23 deletions(-) create mode 100644 packages/website/docs/_samples/main/ComboBox/CustomItems/sample.tsx create mode 100644 packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.tsx diff --git a/packages/main/cypress/specs/ComboBox.cy.tsx b/packages/main/cypress/specs/ComboBox.cy.tsx index 92f04e10217a..0aaf83f56278 100644 --- a/packages/main/cypress/specs/ComboBox.cy.tsx +++ b/packages/main/cypress/specs/ComboBox.cy.tsx @@ -4013,8 +4013,8 @@ describe("ComboBoxItemCustom - Rendering", () => { .find("[ui5-icon]") .realClick(); - cy.get("[ui5-cbi-custom]").eq(0).shadow().find("li").should("contain.text", "🇩🇪 Germany"); - cy.get("[ui5-cbi-custom]").eq(1).shadow().find("li").should("contain.text", "🇫🇷 France"); + cy.get("[ui5-cbi-custom]").eq(0).should("contain.text", "🇩🇪 Germany"); + cy.get("[ui5-cbi-custom]").eq(1).should("contain.text", "🇫🇷 France"); }); it("should mix regular and custom items", () => { @@ -4157,15 +4157,17 @@ describe("ComboBoxItemCustom - Navigation", () => { cy.get("[ui5-combobox]") .as("combobox") + .shadow() + .find("[ui5-icon]") .realClick(); - cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").shadow().find("input").realPress("ArrowDown"); cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); - cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").shadow().find("input").realPress("ArrowDown"); cy.get("[ui5-cbi-custom]").eq(1).should("have.prop", "focused", true); - cy.get("@combobox").realPress("ArrowUp"); + cy.get("@combobox").shadow().find("input").realPress("ArrowUp"); cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); }); @@ -4180,15 +4182,17 @@ describe("ComboBoxItemCustom - Navigation", () => { cy.get("[ui5-combobox]") .as("combobox") + .shadow() + .find("[ui5-icon]") .realClick(); - cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").shadow().find("input").realPress("ArrowDown"); cy.get("[ui5-cb-item]").eq(0).should("have.prop", "focused", true); - cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").shadow().find("input").realPress("ArrowDown"); cy.get("[ui5-cbi-custom]").eq(0).should("have.prop", "focused", true); - cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").shadow().find("input").realPress("ArrowDown"); cy.get("[ui5-cb-item]").eq(1).should("have.prop", "focused", true); }); }); diff --git a/packages/main/cypress/specs/MultiComboBox.cy.tsx b/packages/main/cypress/specs/MultiComboBox.cy.tsx index 9097e95d3763..45952ea505e0 100644 --- a/packages/main/cypress/specs/MultiComboBox.cy.tsx +++ b/packages/main/cypress/specs/MultiComboBox.cy.tsx @@ -5181,8 +5181,8 @@ describe("MultiComboBoxItemCustom - Rendering", () => { .find("[ui5-icon]") .realClick(); - cy.get("[ui5-mcbi-custom]").eq(0).shadow().find(".ui5-li-content").should("contain.text", "🇩🇪 Germany"); - cy.get("[ui5-mcbi-custom]").eq(1).shadow().find(".ui5-li-content").should("contain.text", "🇫🇷 France"); + cy.get("[ui5-mcbi-custom]").eq(0).should("contain.text", "🇩🇪 Germany"); + cy.get("[ui5-mcbi-custom]").eq(1).should("contain.text", "🇫🇷 France"); }); it("should render checkbox for custom items", () => { @@ -5371,7 +5371,7 @@ describe("MultiComboBoxItemCustom - Tokens", () => { .find("[ui5-token]") .eq(0) .shadow() - .find(".ui5-token-icon") + .find("[ui5-icon]") .realClick(); cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "selected", false); @@ -5393,14 +5393,27 @@ describe("MultiComboBoxItemCustom - Navigation", () => { .as("multiCombobox") .realClick(); - cy.get("@multiCombobox").realPress("ArrowDown"); - cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + cy.get("@multiCombobox") + .should("be.focused"); + + cy.get("@multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("@multiCombobox") + .shadow() + .find("ui5-responsive-popover") + .ui5ResponsivePopoverOpened(); - cy.get("@multiCombobox").realPress("ArrowDown"); - cy.get("[ui5-mcbi-custom]").eq(1).should("have.prop", "focused", true); + cy.realPress(["Meta", "ArrowDown"]); + cy.get("[ui5-mcbi-custom]").eq(0).should("be.focused"); - cy.get("@multiCombobox").realPress("ArrowUp"); - cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + cy.realPress(["Meta", "ArrowDown"]); + cy.get("[ui5-mcbi-custom]").eq(1).should("be.focused"); + + cy.realPress(["Meta", "ArrowUp"]); + cy.get("[ui5-mcbi-custom]").eq(0).should("be.focused"); }); it("should navigate through mixed items", () => { @@ -5416,14 +5429,27 @@ describe("MultiComboBoxItemCustom - Navigation", () => { .as("multiCombobox") .realClick(); - cy.get("@multiCombobox").realPress("ArrowDown"); - cy.get("[ui5-mcb-item]").eq(0).should("have.prop", "focused", true); + cy.get("@multiCombobox") + .should("be.focused"); - cy.get("@multiCombobox").realPress("ArrowDown"); - cy.get("[ui5-mcbi-custom]").eq(0).should("have.prop", "focused", true); + cy.get("@multiCombobox") + .shadow() + .find("[ui5-icon]") + .realClick(); - cy.get("@multiCombobox").realPress("ArrowDown"); - cy.get("[ui5-mcb-item]").eq(1).should("have.prop", "focused", true); + cy.get("@multiCombobox") + .shadow() + .find("ui5-responsive-popover") + .ui5ResponsivePopoverOpened(); + + cy.realPress(["Meta", "ArrowDown"]); + cy.get("[ui5-mcb-item]").eq(0).should("be.focused"); + + cy.realPress(["Meta", "ArrowDown"]); + cy.get("[ui5-mcbi-custom]").eq(0).should("be.focused"); + + cy.realPress(["Meta", "ArrowDown"]); + cy.get("[ui5-mcb-item]").eq(1).should("be.focused"); }); }); diff --git a/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.tsx b/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.tsx new file mode 100644 index 000000000000..1c8e6a2fac33 --- /dev/null +++ b/packages/website/docs/_samples/main/ComboBox/CustomItems/sample.tsx @@ -0,0 +1,63 @@ +import { useState } from "react"; +import createReactComponent from "@ui5/webcomponents-base/dist/createReactComponent.js"; +import { type UI5CustomEvent } from "@ui5/webcomponents-base"; +import ComboBoxClass from "@ui5/webcomponents/dist/ComboBox.js"; +import ComboBoxItemCustomClass from "@ui5/webcomponents/dist/ComboBoxItemCustom.js"; + +const ComboBox = createReactComponent(ComboBoxClass); +const ComboBoxItemCustom = createReactComponent(ComboBoxItemCustomClass); + +const countries = [ + { text: "Germany", value: "DE", flag: "🇩🇪" }, + { text: "France", value: "FR", flag: "🇫🇷" }, + { text: "Spain", value: "ES", flag: "🇪🇸" }, + { text: "Italy", value: "IT", flag: "🇮🇹" }, + { text: "United Kingdom", value: "GB", flag: "🇬🇧" }, +]; + +function App() { + const [selectedValue, setSelectedValue] = useState(""); + + const handleChange = (e: UI5CustomEvent) => { + setSelectedValue(e.currentTarget.value); + }; + + return ( + <> + + + {countries.map((country) => ( + + + {country.flag} + + {country.text} + + ))} + + {selectedValue && ( +
+ Selected: {selectedValue} +
+ )} + + ); +} + +export default App; diff --git a/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.tsx b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.tsx new file mode 100644 index 000000000000..ebbf003244b7 --- /dev/null +++ b/packages/website/docs/_samples/main/MultiComboBox/CustomItems/sample.tsx @@ -0,0 +1,68 @@ +import { useState } from "react"; +import createReactComponent from "@ui5/webcomponents-base/dist/createReactComponent.js"; +import { type UI5CustomEvent } from "@ui5/webcomponents-base"; +import MultiComboBoxClass from "@ui5/webcomponents/dist/MultiComboBox.js"; +import MultiComboBoxItemCustomClass from "@ui5/webcomponents/dist/MultiComboBoxItemCustom.js"; + +const MultiComboBox = createReactComponent(MultiComboBoxClass); +const MultiComboBoxItemCustom = createReactComponent(MultiComboBoxItemCustomClass); + +const countries = [ + { text: "Germany", value: "DE", flag: "🇩🇪" }, + { text: "France", value: "FR", flag: "🇫🇷" }, + { text: "Spain", value: "ES", flag: "🇪🇸" }, + { text: "Italy", value: "IT", flag: "🇮🇹" }, + { text: "United Kingdom", value: "GB", flag: "🇬🇧" }, +]; + +function App() { + const [selectedValues, setSelectedValues] = useState([]); + + const handleSelectionChange = (e: UI5CustomEvent) => { + const items = e.currentTarget.items; + setSelectedValues( + items + .filter((item: any) => item.selected) + .map((item: any) => item.text) + ); + }; + + return ( + <> + + + {countries.map((country) => ( + + + {country.flag} + + {country.text} + + ))} + + {selectedValues.length > 0 && ( +
+ Selected: {selectedValues.join(", ")} +
+ )} + + ); +} + +export default App; From 02fb8ce8b54ff1ac87f20899859cfc28cf98f74c Mon Sep 17 00:00:00 2001 From: Milen Karmidzhanov Date: Thu, 4 Jun 2026 13:05:37 +0300 Subject: [PATCH 3/5] feat(ui5-comobobox, ui5-multi-combobox): add custom items --- packages/main/src/bundle.esm.ts | 2 ++ .../_components_pages/main/ComboBox/ComboBoxItemCustom.mdx | 7 +++++++ .../main/MultiComboBox/MultiComboBoxItemCustom.mdx | 7 +++++++ 3 files changed, 16 insertions(+) create mode 100644 packages/website/docs/_components_pages/main/ComboBox/ComboBoxItemCustom.mdx create mode 100644 packages/website/docs/_components_pages/main/MultiComboBox/MultiComboBoxItemCustom.mdx diff --git a/packages/main/src/bundle.esm.ts b/packages/main/src/bundle.esm.ts index f770e818a792..d916b641dfac 100644 --- a/packages/main/src/bundle.esm.ts +++ b/packages/main/src/bundle.esm.ts @@ -47,6 +47,7 @@ import ColorPaletteItem from "./ColorPaletteItem.js"; import ColorPalettePopover from "./ColorPalettePopover.js"; import ColorPicker from "./ColorPicker.js"; import ComboBox from "./ComboBox.js"; +import ComboBoxItemCustom from "./ComboBoxItemCustom.js"; import DatePicker from "./DatePicker.js"; import DateRangePicker from "./DateRangePicker.js"; import DateTimePicker from "./DateTimePicker.js"; @@ -109,6 +110,7 @@ import RangeSlider from "./RangeSlider.js"; import Switch from "./Switch.js"; import MessageStrip from "./MessageStrip.js"; import MultiComboBox from "./MultiComboBox.js"; +import MultiComboBoxItemCustom from "./MultiComboBoxItemCustom.js"; import ProgressIndicator from "./ProgressIndicator.js"; import RatingIndicator from "./RatingIndicator.js"; import Tag from "./Tag.js"; diff --git a/packages/website/docs/_components_pages/main/ComboBox/ComboBoxItemCustom.mdx b/packages/website/docs/_components_pages/main/ComboBox/ComboBoxItemCustom.mdx new file mode 100644 index 000000000000..c5e477222e81 --- /dev/null +++ b/packages/website/docs/_components_pages/main/ComboBox/ComboBoxItemCustom.mdx @@ -0,0 +1,7 @@ +--- +slug: ../../ComboBoxItemCustom +--- + +<%COMPONENT_OVERVIEW%> + +<%COMPONENT_METADATA%> diff --git a/packages/website/docs/_components_pages/main/MultiComboBox/MultiComboBoxItemCustom.mdx b/packages/website/docs/_components_pages/main/MultiComboBox/MultiComboBoxItemCustom.mdx new file mode 100644 index 000000000000..848e8db046f4 --- /dev/null +++ b/packages/website/docs/_components_pages/main/MultiComboBox/MultiComboBoxItemCustom.mdx @@ -0,0 +1,7 @@ +--- +slug: ../../MultiComboBoxItemCustom +--- + +<%COMPONENT_OVERVIEW%> + +<%COMPONENT_METADATA%> From c129bc83e672f9d241ac2b1498c9d782d264ae88 Mon Sep 17 00:00:00 2001 From: Milen Karmidzhanov Date: Thu, 4 Jun 2026 13:10:30 +0300 Subject: [PATCH 4/5] feat(ui5-comobobox, ui5-multi-combobox): add custom items --- packages/main/src/ComboBoxItemCustom.ts | 1 + packages/main/src/MultiComboBoxItemCustom.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/main/src/ComboBoxItemCustom.ts b/packages/main/src/ComboBoxItemCustom.ts index ad1a5cd85f56..b85e2cec72f9 100644 --- a/packages/main/src/ComboBoxItemCustom.ts +++ b/packages/main/src/ComboBoxItemCustom.ts @@ -12,6 +12,7 @@ import type { DefaultSlot } from "@ui5/webcomponents-base/dist/UI5Element.js"; * The `ui5-cbi-custom` is type of combobox item, * that can be used to place combobox items with custom content in the combobox. * The text property is considered for filtering and autocomplete. + * In case the user needs highlighting functionality, check "@ui5/webcomponents-base/dist/util/generateHighlightedMarkup.js" * * @constructor * @extends ListItemBase diff --git a/packages/main/src/MultiComboBoxItemCustom.ts b/packages/main/src/MultiComboBoxItemCustom.ts index 1a5eee698dd0..eced507096f6 100644 --- a/packages/main/src/MultiComboBoxItemCustom.ts +++ b/packages/main/src/MultiComboBoxItemCustom.ts @@ -21,6 +21,7 @@ import type { AriaRole } from "@ui5/webcomponents-base"; * The `ui5-mcbi-custom` is type of multi-combobox item, * that can be used to place multi-combobox items with custom content. * The text property is considered for filtering and token display. + * In case the user needs highlighting functionality, check "@ui5/webcomponents-base/dist/util/generateHighlightedMarkup.js" * * @constructor * @extends ComboBoxItemCustom From e677faef0c04919a920eefaa414f82d0202abf7a Mon Sep 17 00:00:00 2001 From: Milen Karmidzhanov Date: Thu, 4 Jun 2026 13:50:44 +0300 Subject: [PATCH 5/5] feat(ui5-comobobox, ui5-multi-combobox): add custom items --- packages/main/src/ComboBoxItemCustom.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/main/src/ComboBoxItemCustom.ts b/packages/main/src/ComboBoxItemCustom.ts index b85e2cec72f9..8b1c9e8d7818 100644 --- a/packages/main/src/ComboBoxItemCustom.ts +++ b/packages/main/src/ComboBoxItemCustom.ts @@ -36,7 +36,6 @@ class ComboBoxItemCustom extends ListItemBase implements IComboBoxItem { * Used for filtering, autocomplete, and mobile rendering. * @default undefined * @public - * @since 2.24.0 */ @property() text?: string; @@ -46,7 +45,6 @@ class ComboBoxItemCustom extends ListItemBase implements IComboBoxItem { * Used for programmatic selection via selectedValue property. * @default undefined * @public - * @since 2.24.0 */ @property() value?: string; @@ -68,7 +66,6 @@ class ComboBoxItemCustom extends ListItemBase implements IComboBoxItem { /** * Defines the content of the component. * @public - * @since 2.24.0 */ @slot({ type: Node, "default": true, invalidateOnChildChange: true }) content!: DefaultSlot;