diff --git a/.changeset/yellow-steaks-tie.md b/.changeset/yellow-steaks-tie.md
new file mode 100644
index 000000000..c886c37dd
--- /dev/null
+++ b/.changeset/yellow-steaks-tie.md
@@ -0,0 +1,5 @@
+---
+'@lion/ui': patch
+---
+
+[input-tel-dropdown] prevent jumping to input field on each arrow key in windows/linux
diff --git a/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js b/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js
index 0100f9b6e..328264334 100644
--- a/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js
+++ b/packages/ui/components/input-tel-dropdown/src/LionInputTelDropdown.js
@@ -324,7 +324,10 @@ export class LionInputTelDropdown extends LionInputTel {
*/
_onDropdownValueChange(event) {
const isInitializing = event.detail?.initialize || !this._phoneUtil;
- const dropdownValue = /** @type {RegionCode} */ (event.target.modelValue || event.target.value);
+ const dropdownElement = event.target;
+ const dropdownValue = /** @type {RegionCode} */ (
+ dropdownElement.modelValue || dropdownElement.value
+ );
if (isInitializing || this.activeRegion === dropdownValue) {
return;
@@ -355,8 +358,13 @@ export class LionInputTelDropdown extends LionInputTel {
}
// Put focus on text box
- const overlayController = event.target._overlayCtrl;
- if (overlayController?.isShown) {
+ //
+ // A LionSelectRich with interactionMode set on windows/linux
+ // will set each item on arrow key up/down to activeElement
+ // which causes the focus to jump every time to the inputNode
+ const overlayController = dropdownElement._overlayCtrl;
+ // @ts-ignore interactionMode only exists on LionSelectRich not on HTMLSelectElement
+ if (overlayController?.isShown && dropdownElement.interactionMode !== 'windows/linux') {
setTimeout(() => {
this._inputNode.focus();
});
diff --git a/packages/ui/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js b/packages/ui/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js
new file mode 100644
index 000000000..c320146d6
--- /dev/null
+++ b/packages/ui/components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js
@@ -0,0 +1,22 @@
+/**
+ * @typedef {HTMLSelectElement|HTMLElement & {modelValue:string}} DropdownElement
+ */
+
+/**
+ * @param {DropdownElement} dropdownEl
+ * @param {string} value
+ */
+export function mimicUserChangingDropdown(dropdownEl, value) {
+ if ('modelValue' in dropdownEl) {
+ // eslint-disable-next-line no-param-reassign
+ dropdownEl.modelValue = value;
+ dropdownEl.dispatchEvent(
+ new CustomEvent('model-value-changed', { detail: { isTriggeredByUser: true } }),
+ );
+ } else {
+ // eslint-disable-next-line no-param-reassign
+ dropdownEl.value = value;
+ dropdownEl.dispatchEvent(new Event('change'));
+ dropdownEl.dispatchEvent(new Event('input'));
+ }
+}
diff --git a/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js b/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js
index 053d2e9e2..5523b5dbd 100644
--- a/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js
+++ b/packages/ui/components/input-tel-dropdown/test-suites/LionInputTelDropdown.suite.js
@@ -11,6 +11,7 @@ import {
} from '@open-wc/testing';
import sinon from 'sinon';
import { LionInputTelDropdown } from '@lion/ui/input-tel-dropdown.js';
+import { mimicUserChangingDropdown } from '@lion/ui/input-tel-dropdown-test-helpers.js';
/**
* @typedef {import('lit').TemplateResult} TemplateResult
@@ -36,24 +37,6 @@ function getDropdownValue(dropdownEl) {
return dropdownEl.value;
}
-/**
- * @param {DropdownElement} dropdownEl
- * @param {string} value
- */
-function mimicUserChangingDropdown(dropdownEl, value) {
- if ('modelValue' in dropdownEl) {
- // eslint-disable-next-line no-param-reassign
- dropdownEl.modelValue = value;
- dropdownEl.dispatchEvent(
- new CustomEvent('model-value-changed', { detail: { isTriggeredByUser: true } }),
- );
- } else {
- // eslint-disable-next-line no-param-reassign
- dropdownEl.value = value;
- dropdownEl.dispatchEvent(new Event('change'));
- }
-}
-
/**
* @param {{ klass:LionInputTelDropdown }} config
*/
@@ -335,26 +318,6 @@ export function runInputTelDropdownSuite({ klass } = { klass: LionInputTelDropdo
expect(el.value).to.equal('+32');
});
- it('focuses the textbox right after selection if selected via opened dropdown', async () => {
- const el = await fixture(
- html` <${tag} .allowedRegions="${[
- 'NL',
- 'BE',
- ]}" .modelValue="${'+31612345678'}">${tag}> `,
- );
- const dropdownElement = el.refs.dropdown.value;
- // @ts-expect-error [allow-protected-in-tests]
- if (dropdownElement?._overlayCtrl) {
- // @ts-expect-error [allow-protected-in-tests]
- dropdownElement._overlayCtrl.show();
- mimicUserChangingDropdown(dropdownElement, 'BE');
- await el.updateComplete;
- await aTimeout(0);
- // @ts-expect-error [allow-protected-in-tests]
- expect(el._inputNode).to.equal(document.activeElement);
- }
- });
-
it('keeps focus on dropdownElement after selection if selected via unopened dropdown', async () => {
const el = await fixture(
html` <${tag} .allowedRegions="${[
diff --git a/packages/ui/components/input-tel-dropdown/test/LionInputTelDropdown.test.js b/packages/ui/components/input-tel-dropdown/test/LionInputTelDropdown.test.js
index 8ca519cef..15753bd38 100644
--- a/packages/ui/components/input-tel-dropdown/test/LionInputTelDropdown.test.js
+++ b/packages/ui/components/input-tel-dropdown/test/LionInputTelDropdown.test.js
@@ -1,10 +1,10 @@
import { runInputTelSuite } from '@lion/ui/input-tel-test-suites.js';
-import { html } from 'lit';
import { repeat } from 'lit/directives/repeat.js';
import { ref } from 'lit/directives/ref.js';
-
+import { aTimeout, expect, fixture, html } from '@open-wc/testing';
import { LionInputTelDropdown } from '@lion/ui/input-tel-dropdown.js';
import { runInputTelDropdownSuite } from '@lion/ui/input-tel-dropdown-test-suites.js';
+import { mimicUserChangingDropdown } from '@lion/ui/input-tel-dropdown-test-helpers.js';
import '@lion/ui/define/lion-option.js';
import '@lion/ui/define/lion-select-rich.js';
@@ -53,4 +53,112 @@ describe('WithFormControlInputTelDropdown', () => {
// @ts-expect-error
// Runs it for LionSelectRich, which uses .modelValue/@model-value-changed instead of .value/@change
runInputTelDropdownSuite({ klass: WithFormControlInputTelDropdown });
+
+ it('focuses the textbox right after selection if selected via opened dropdown if interaction-mode is mac', async () => {
+ class InputTelDropdownMac extends LionInputTelDropdown {
+ static templates = {
+ ...(super.templates || {}),
+ /**
+ * @param {TemplateDataForDropdownInputTel} templateDataForDropdown
+ */
+ dropdown: templateDataForDropdown => {
+ const { refs, data } = templateDataForDropdown;
+ // TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
+ return html`
+
+ ${repeat(
+ data.regionMetaList,
+ regionMeta => regionMeta.regionCode,
+ regionMeta =>
+ html` `,
+ )}
+
+ `;
+ },
+ };
+ }
+ customElements.define('input-tel-dropdown-mac', InputTelDropdownMac);
+ const el = /** @type {LionInputTelDropdown} */ (
+ await fixture(
+ html`
+
+ `,
+ )
+ );
+ const dropdownElement = el.refs.dropdown.value;
+ // @ts-expect-error [allow-protected-in-tests]
+ if (dropdownElement?._overlayCtrl) {
+ // @ts-expect-error [allow-protected-in-tests]
+ dropdownElement._overlayCtrl.show();
+ mimicUserChangingDropdown(dropdownElement, 'BE');
+ await el.updateComplete;
+ await aTimeout(0);
+ // @ts-expect-error [allow-protected-in-tests]
+ expect(el._inputNode).to.equal(document.activeElement);
+ }
+ });
+
+ it('does not focus the textbox right after selection if selected via opened dropdown if interaction-mode is windows/linux', async () => {
+ class InputTelDropdownWindows extends LionInputTelDropdown {
+ static templates = {
+ ...(super.templates || {}),
+ /**
+ * @param {TemplateDataForDropdownInputTel} templateDataForDropdown
+ */
+ dropdown: templateDataForDropdown => {
+ const { refs, data } = templateDataForDropdown;
+ // TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
+ return html`
+
+ ${repeat(
+ data.regionMetaList,
+ regionMeta => regionMeta.regionCode,
+ regionMeta =>
+ html` `,
+ )}
+
+ `;
+ },
+ };
+ }
+ customElements.define('input-tel-dropdown-windows', InputTelDropdownWindows);
+ const el = /** @type {LionInputTelDropdown} */ (
+ await fixture(
+ html`
+
+ `,
+ )
+ );
+ const dropdownElement = el.refs.dropdown.value;
+ // @ts-expect-error [allow-protected-in-tests]
+ if (dropdownElement?._overlayCtrl) {
+ // @ts-expect-error [allow-protected-in-tests]
+ dropdownElement._overlayCtrl.show();
+ mimicUserChangingDropdown(dropdownElement, 'BE');
+ await el.updateComplete;
+ await aTimeout(0);
+ // @ts-expect-error [allow-protected-in-tests]
+ expect(el._inputNode).to.not.equal(document.activeElement);
+ }
+ });
});
diff --git a/packages/ui/exports/input-tel-dropdown-test-helpers.js b/packages/ui/exports/input-tel-dropdown-test-helpers.js
new file mode 100644
index 000000000..3d3b171fc
--- /dev/null
+++ b/packages/ui/exports/input-tel-dropdown-test-helpers.js
@@ -0,0 +1 @@
+export { mimicUserChangingDropdown } from '../components/input-tel-dropdown/test-helpers/mimicUserChangingDropdown.js';