diff --git a/packages/main/cypress/specs/Tokenizer.cy.tsx b/packages/main/cypress/specs/Tokenizer.cy.tsx
index c30ae1259df1..310c7003a0ef 100755
--- a/packages/main/cypress/specs/Tokenizer.cy.tsx
+++ b/packages/main/cypress/specs/Tokenizer.cy.tsx
@@ -1566,3 +1566,80 @@ describe("Keyboard Handling", () => {
.should("have.attr", "selected");
});
});
+
+describe("Tokenizer - getFocusDomRef Method", () => {
+ it("should focus the last focused token on tokenizer focus if its visible", () => {
+ const onButtonClick = () => {
+ document.getElementById("tokenizer").focus();
+ }
+ cy.mount(
+ <>
+
+
+
+
+
+
+
+
+ >
+ );
+
+ cy.get("[ui5-token]")
+ .eq(1)
+ .realClick();
+
+ cy.get("[ui5-button]")
+ .eq(0)
+ .realClick();
+
+ cy.get("[ui5-button]")
+ .eq(1)
+ .realClick();
+
+ cy.get("[ui5-token]")
+ .eq(1)
+ .should("be.focused");
+ });
+
+ it("should focus the first token if the previously focused token is not visible", () => {
+ const onButtonClick = () => {
+ document.getElementById("nmore-token").focus();
+ }
+ cy.mount(
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+
+ cy.get("[ui5-button]")
+ .eq(1)
+ .realClick();
+
+ cy.get("[ui5-token]")
+ .eq(2)
+ .realClick();
+
+ cy.get("[ui5-button]")
+ .eq(0)
+ .realClick();
+
+ cy.get("[ui5-button]")
+ .eq(1)
+ .realClick();
+
+ cy.get("[ui5-token]")
+ .eq(0)
+ .should("be.focused");
+ });
+});
diff --git a/packages/main/src/Tokenizer.ts b/packages/main/src/Tokenizer.ts
index 2ee34d93796c..3fdd45f81874 100644
--- a/packages/main/src/Tokenizer.ts
+++ b/packages/main/src/Tokenizer.ts
@@ -364,6 +364,8 @@ class Tokenizer extends UI5Element implements IFormInputElement {
_previousToken: Token | null = null;
_focusedElementBeforeOpen?: HTMLElement | null;
_deletedDialogItems!: Token[];
+ _lastFocusedToken: Token | null = null;
+ _isFocusSetInternally: boolean = false;
/**
* Scroll to end when tokenizer is expanded
* @private
@@ -496,7 +498,7 @@ class Tokenizer extends UI5Element implements IFormInputElement {
this._nMoreCount = this.overflownTokens.length;
- if (firstToken && !this.disabled && !this.preventInitialFocus && !this._skipTabIndex) {
+ if (firstToken && !this.disabled && !this.preventInitialFocus && !this._skipTabIndex && !this._isFocusSetInternally) {
firstToken.forcedTabIndex = "0";
}
@@ -946,6 +948,7 @@ class Tokenizer extends UI5Element implements IFormInputElement {
_onfocusin(e: FocusEvent) {
const target = e.target as Token;
+ this._lastFocusedToken = target;
if (target && target.toBeDeleted) {
this._tokenDeleting = true;
@@ -975,6 +978,7 @@ class Tokenizer extends UI5Element implements IFormInputElement {
if (!this.contains(relatedTarget)) {
this._tokens[0].forcedTabIndex = "0";
+ this._isFocusSetInternally = false;
this._skipTabIndex = false;
}
@@ -984,6 +988,22 @@ class Tokenizer extends UI5Element implements IFormInputElement {
}
}
+ /**
+ * Determines the DOM element to focus when the Tokenizer receives focus.
+ * If the last-focused token is not overflown, focus is restored to it.
+ * Otherwise, the focus defaults to the first visible token.
+ */
+ getFocusDomRef(): HTMLElement | undefined {
+ if (this._lastFocusedToken && !this.overflownTokens.includes(this._lastFocusedToken)) {
+ this._itemNav._currentIndex = this.tokens.indexOf(this._lastFocusedToken);
+ this._isFocusSetInternally = true;
+ this.tokens[0].forcedTabIndex = "-1";
+ } else {
+ this._itemNav._currentIndex = 0;
+ }
+ return this._itemNav._getCurrentItem();
+ }
+
_toggleTokenSelection(tokens: Array) {
if (!tokens || !tokens.length) {
return;