diff --git a/packages/main/src/RadioButton.js b/packages/main/src/RadioButton.js index 1084f6786a47..e5b684884ae0 100644 --- a/packages/main/src/RadioButton.js +++ b/packages/main/src/RadioButton.js @@ -161,6 +161,12 @@ const metadata = { wrap: { type: Boolean, }, + + _tabIndex: { + type: String, + defaultValue: "-1", + noAttribute: true, + }, }, events: /** @lends sap.ui.webcomponents.main.RadioButton.prototype */ { @@ -240,13 +246,14 @@ class RadioButton extends UI5Element { onBeforeRendering() { this.syncGroup(); - this._enableFormSupport(); } syncGroup() { const oldGroup = this._name; const currentGroup = this.name; + const oldSelected = this._selected; + const currentSelected = this.selected; if (currentGroup !== oldGroup) { if (oldGroup) { @@ -262,7 +269,12 @@ class RadioButton extends UI5Element { RadioButtonGroup.enforceSingleSelection(this, currentGroup); } + if (this.name && currentSelected !== oldSelected) { + RadioButtonGroup.updateTabOrder(this.name); + } + this._name = this.name; + this._selected = this.selected; } _enableFormSupport() { @@ -395,7 +407,7 @@ class RadioButton extends UI5Element { } if (this.name) { - return this.selected ? "0" : "-1"; + return this._tabIndex; } return tabindex || "0"; diff --git a/packages/main/src/RadioButtonGroup.js b/packages/main/src/RadioButtonGroup.js index 19f910e43a33..e61cdabd9d64 100644 --- a/packages/main/src/RadioButtonGroup.js +++ b/packages/main/src/RadioButtonGroup.js @@ -23,6 +23,8 @@ class RadioButtonGroup { } else { this.createGroup(radioBtn, groupName); } + + this.updateTabOrder(groupName); } static removeFromGroup(radioBtn, groupName) { @@ -48,6 +50,8 @@ class RadioButtonGroup { if (!group.length) { this.removeGroup(groupName); } + + this.updateTabOrder(groupName); } static createGroup(radioBtn, groupName) { @@ -72,6 +76,23 @@ class RadioButtonGroup { this.updateSelectionInGroup(nextItemToSelect, groupName); } + static updateTabOrder(groupName) { + if (!this.hasGroup(groupName)) { + return; + } + + const group = this.getGroup(groupName); + const hasSelectedRadio = group.some(radioBtn => radioBtn.selected); + + group.filter(radioBtn => !radioBtn.disabled).forEach((radioBtn, idx) => { + if (hasSelectedRadio) { + radioBtn._tabIndex = radioBtn.selected ? "0" : "-1"; + } else { + radioBtn._tabIndex = idx === 0 ? "0" : "-1"; + } + }); + } + static selectPreviousItem(item, groupName) { const group = this.getGroup(groupName), groupLength = group.length, @@ -88,6 +109,7 @@ class RadioButtonGroup { static selectItem(item, groupName) { this.updateSelectionInGroup(item, groupName); + this.updateTabOrder(groupName); } static updateSelectionInGroup(radioBtnToSelect, groupName) { @@ -161,6 +183,8 @@ class RadioButtonGroup { } else if (radioBtn === selectedRadio) { this.selectedRadios.set(groupName, null); } + + this.updateTabOrder(groupName); } static get groups() { diff --git a/packages/main/test/pages/RadioButton.html b/packages/main/test/pages/RadioButton.html index 5251f3c24750..644925f827fa 100644 --- a/packages/main/test/pages/RadioButton.html +++ b/packages/main/test/pages/RadioButton.html @@ -17,50 +17,57 @@ .radio-section { display: flex; flex-direction: column; + margin-bottom: 2rem; } - ui5-radiobutton - - - - - > -
- - + Radios within a group
+
+ Group1 - None pre-selection + + + +
+ +
+ Group 2 + + + +
- ui5-radiobutton in group + Group 3 + - +
- ui5-radiobutton in group + Group 4
-
- Group of states - - +
+ Group 4 - Value states + N/A + 0 - -
+ + + Standalone Radios Not Grouped
- ui5-radiobutton states

@@ -72,6 +79,18 @@
+ +
+ + + + + > +
+ + +
+

*Params

- for compact add 'ui5-content-density-compact' class to any dom element diff --git a/packages/main/test/specs/RadioButton.spec.js b/packages/main/test/specs/RadioButton.spec.js index c614ae021ef5..467747978d7b 100644 --- a/packages/main/test/specs/RadioButton.spec.js +++ b/packages/main/test/specs/RadioButton.spec.js @@ -56,7 +56,7 @@ describe("RadioButton general interaction", () => { }); it("tests radio buttons selection within group with ARROW-RIGHT key", () => { - const field = browser.$("#field"); + const field = browser.$("#tabField"); const radioButtonPreviouslySelected = browser.$("#groupRb1"); const radioButtonToBeSelected = browser.$("#groupRb3"); @@ -81,14 +81,38 @@ describe("RadioButton general interaction", () => { assert.ok(radioButtonToBeSelected.getProperty("selected"), "Pressing ArrowLeft selects the next (not disabled) radio in the group."); }); + it("tests tabindex within group with selected item", () => { + const selectedRadio = browser.$("#testRbtn11").shadow$(".ui5-radio-root"); + const disabledRadio = browser.$("#testRbtn12").shadow$(".ui5-radio-root"); + const radio = browser.$("#testRbtn13").shadow$(".ui5-radio-root"); + + assert.strictEqual(selectedRadio.getAttribute("tabindex"), "0", "The selected radio has tabindex = 0"); + assert.strictEqual(disabledRadio.getAttribute("tabindex"), "-1", "The disabled radio has tabindex = -1"); + assert.strictEqual(radio.getAttribute("tabindex"), "-1", "None selected item has tabindex = -1"); + }); + + it("tests tabindex within group with no selected item", () => { + const radio1 = browser.$("#testRbtn1").shadow$(".ui5-radio-root"); + const radio2 = browser.$("#testRbtn2").shadow$(".ui5-radio-root"); + + assert.strictEqual(radio1.getAttribute("tabindex"), "0", "The first radio has tabindex = 0"); + assert.strictEqual(radio2.getAttribute("tabindex"), "-1", "The other radio has tabindex = -1"); + }); + it("tests radio buttons selection within group by clicking", () => { const radioButtonPreviouslySelected = browser.$("#groupRb6"); + const radioButtonPreviouslySelectedRoot = browser.$("#groupRb6").shadow$(".ui5-radio-root"); + const radioButtonToBeSelected = browser.$("#groupRb4"); + const radioButtonToBeSelectedRoot = browser.$("#groupRb4").shadow$(".ui5-radio-root"); radioButtonToBeSelected.click(); assert.ok(!radioButtonPreviouslySelected.getProperty("selected"), "Previously selected item has been de-selected."); + assert.strictEqual(radioButtonPreviouslySelectedRoot.getAttribute("tabindex"), "-1", "The previously selected radio has tabindex = -1"); + assert.ok(radioButtonToBeSelected.getProperty("selected"), "Pressing ArrowRight selects the next (not disabled) radio in the group."); + assert.strictEqual(radioButtonToBeSelectedRoot.getAttribute("tabindex"), "0", "The newly selected radio has tabindex = 0"); }); it("tests single selection within group, even if multiple radios are set as selected", () => {