diff --git a/.changeset/spotty-emus-allow.md b/.changeset/spotty-emus-allow.md
new file mode 100644
index 000000000..27a1bf762
--- /dev/null
+++ b/.changeset/spotty-emus-allow.md
@@ -0,0 +1,5 @@
+---
+'@lion/ui': patch
+---
+
+[select-rich] allow arrowLeft and arrowRight to change the value when navigateWithinInvoker is true and dropdown is closed
diff --git a/packages/ui/components/select-rich/src/LionSelectRich.js b/packages/ui/components/select-rich/src/LionSelectRich.js
index 06d798d5c..28b176600 100644
--- a/packages/ui/components/select-rich/src/LionSelectRich.js
+++ b/packages/ui/components/select-rich/src/LionSelectRich.js
@@ -529,6 +529,22 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
this.opened = true;
}
break;
+ case 'ArrowLeft':
+ ev.preventDefault();
+ if (this.navigateWithinInvoker) {
+ this.setCheckedIndex(
+ this._getPreviousEnabledOption(/** @type {number} */ (this.checkedIndex)),
+ );
+ }
+ break;
+ case 'ArrowRight':
+ ev.preventDefault();
+ if (this.navigateWithinInvoker) {
+ this.setCheckedIndex(
+ this._getNextEnabledOption(/** @type {number} */ (this.checkedIndex)),
+ );
+ }
+ break;
default:
if (!this._noTypeAhead) {
this._handleTypeAhead(ev, { setAsChecked: true });
diff --git a/packages/ui/components/select-rich/test/lion-select-rich-interaction.test.js b/packages/ui/components/select-rich/test/lion-select-rich-interaction.test.js
index ef43ec63e..72a55d29e 100644
--- a/packages/ui/components/select-rich/test/lion-select-rich-interaction.test.js
+++ b/packages/ui/components/select-rich/test/lion-select-rich-interaction.test.js
@@ -24,6 +24,24 @@ function mimicKeyPress(el, key, code = '') {
el.dispatchEvent(new KeyboardEvent('keyup', { key, code }));
}
+/**
+ * @param {LionOption[]} options
+ * @param {number} selectedIndex
+ */
+function expectOnlyGivenOneOptionToBeChecked(options, selectedIndex) {
+ /**
+ * @param {{ checked: any; }} option
+ * @param {any} i
+ */
+ options.forEach((option, i) => {
+ if (i === selectedIndex) {
+ expect(option.checked).to.be.true;
+ } else {
+ expect(option.checked).to.be.false;
+ }
+ });
+}
+
describe('lion-select-rich interactions', () => {
describe('Interaction mode', () => {
it('autodetects interactionMode if not defined', async () => {
@@ -86,26 +104,91 @@ describe('lion-select-rich interactions', () => {
});
});
- describe('Invoker Keyboard navigation Windows', () => {
- it('navigates through list with [ArrowDown] [ArrowUp] keys checks the option while listbox unopened', async () => {
- /**
- * @param {LionOption[]} options
- * @param {number} selectedIndex
- */
- function expectOnlyGivenOneOptionToBeChecked(options, selectedIndex) {
- /**
- * @param {{ checked: any; }} option
- * @param {any} i
- */
- options.forEach((option, i) => {
- if (i === selectedIndex) {
- expect(option.checked).to.be.true;
- } else {
- expect(option.checked).to.be.false;
- }
- });
- }
+ describe('Invoker Keyboard navigation Mac', () => {
+ it('opens dropdown with [ArrowDown] [ArrowUp] keys or navigates through the listbox options', async () => {
+ const el = /** @type {LionSelectRich} */ (
+ await fixture(html`
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+ `)
+ );
+
+ const options = el.formElements;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowDown' }));
+
+ expect(el.opened).to.be.true;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+
+ el.opened = false;
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowUp' }));
+ expect(el.opened).to.be.true;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+ });
+
+ it('does not open dropdown with [ArrowLeft] [ArrowRight] keys or navigates through the listbox options', async () => {
+ const el = /** @type {LionSelectRich} */ (
+ await fixture(html`
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+ `)
+ );
+
+ const options = el.formElements;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowLeft' }));
+
+ expect(el.opened).to.be.false;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowRight' }));
+ expect(el.opened).to.be.false;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+ });
+
+ it('checks a value with [character] keys while listbox unopened', async () => {
+ const el = /** @type {LionSelectRich} */ (
+ await fixture(html`
+
+
+ Red
+ Teal
+ Turquoise
+
+
+ `)
+ );
+
+ // @ts-ignore [allow-private] in test
+ mimicKeyPress(el, 't', 'KeyT');
+ expect(el.checkedIndex).to.equal(1);
+
+ mimicKeyPress(el, 'u', 'KeyU');
+ expect(el.checkedIndex).to.equal(2);
+ });
+ });
+ describe('Invoker Keyboard navigation Windows/Linux', () => {
+ it('navigates through list with [ArrowDown] [ArrowUp] keys checks the option while listbox unopened', async () => {
let isTriggeredByUser;
const el = /** @type {LionSelectRich} */ (
await fixture(html`
@@ -141,7 +224,43 @@ describe('lion-select-rich interactions', () => {
expect(isTriggeredByUser).to.be.true;
});
- it('checkes a value with [character] keys while listbox unopened', async () => {
+ it('navigates through list with [ArrowLeft] [ArrowRight] keys checks the option while listbox unopened', async () => {
+ let isTriggeredByUser;
+ const el = /** @type {LionSelectRich} */ (
+ await fixture(html`
+ {
+ isTriggeredByUser = event.detail.isTriggeredByUser;
+ }}"
+ >
+
+ Item 1
+ Item 2
+ Item 3
+
+
+ `)
+ );
+
+ const options = el.formElements;
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowRight' }));
+ expect(el.checkedIndex).to.equal(1);
+ expectOnlyGivenOneOptionToBeChecked(options, 1);
+ expect(isTriggeredByUser).to.be.true;
+
+ isTriggeredByUser = false;
+
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: 'ArrowLeft' }));
+ expect(el.checkedIndex).to.equal(0);
+ expectOnlyGivenOneOptionToBeChecked(options, 0);
+ expect(isTriggeredByUser).to.be.true;
+ });
+
+ it('checks a value with [character] keys while listbox unopened', async () => {
const el = /** @type {LionSelectRich} */ (
await fixture(html`