From dd6a483cccaadc077536c5c9dc4b759670e7a2e1 Mon Sep 17 00:00:00 2001 From: Mudit Choudhary Date: Mon, 3 Jun 2024 15:37:46 +0530 Subject: [PATCH 01/21] Add new KRadioButtonGroup Component - This component enables focus movenment on radio buttons with arrow keys on firefox --- lib/KRadioButtonGroup.vue | 114 ++++++++++++++++++++++++++++++++++++++ lib/KThemePlugin.js | 2 + 2 files changed, 116 insertions(+) create mode 100644 lib/KRadioButtonGroup.vue diff --git a/lib/KRadioButtonGroup.vue b/lib/KRadioButtonGroup.vue new file mode 100644 index 000000000..b5c2f3ca6 --- /dev/null +++ b/lib/KRadioButtonGroup.vue @@ -0,0 +1,114 @@ + + + diff --git a/lib/KThemePlugin.js b/lib/KThemePlugin.js index 9e189f875..0b18c6652 100644 --- a/lib/KThemePlugin.js +++ b/lib/KThemePlugin.js @@ -34,6 +34,7 @@ import KTooltip from './KTooltip'; import KTransition from './KTransition'; import KTextTruncator from './KTextTruncator'; import KLogo from './KLogo'; +import KRadioButtonGroup from './KRadioButtonGroup.vue'; import { themeTokens, themeBrand, themePalette, themeOutlineStyle } from './styles/theme'; import globalThemeState from './styles/globalThemeState'; @@ -127,4 +128,5 @@ export default function KThemePlugin(Vue) { Vue.component('KTooltip', KTooltip); Vue.component('KTransition', KTransition); Vue.component('KTextTruncator', KTextTruncator); + Vue.component('KRadioButtonGroup', KRadioButtonGroup); } From ea5a9f13713128408229b3a52f4f7227e26448c3 Mon Sep 17 00:00:00 2001 From: Mudit Choudhary Date: Mon, 3 Jun 2024 16:24:22 +0530 Subject: [PATCH 02/21] Add setTabIndex method to set tab index on each radio component --- lib/KRadioButton.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/KRadioButton.vue b/lib/KRadioButton.vue index f83a4519d..414c2f89d 100644 --- a/lib/KRadioButton.vue +++ b/lib/KRadioButton.vue @@ -8,6 +8,7 @@ ref="input" v-autofocus="autofocus" type="radio" + :tabindex="tabIndex" class="k-radio-button-input" :checked="isChecked" :value="buttonValue !== null ? buttonValue : value" @@ -148,6 +149,7 @@ }, data: () => ({ active: false, + tabIndex: 0, }), computed: { isChecked() { @@ -220,6 +222,12 @@ */ this.$emit('blur'); }, + /** + * @public + */ + setTabIndex(val) { + this.tabIndex = val; + }, }, }; From 6100a156f44aedaa436fcac639d2c045910cfda5 Mon Sep 17 00:00:00 2001 From: Mudit Choudhary Date: Tue, 4 Jun 2024 15:26:21 +0530 Subject: [PATCH 03/21] Add test for KRadioButtonGroup component --- lib/__tests__/KRadioButtonGroup.spec.js | 96 +++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 lib/__tests__/KRadioButtonGroup.spec.js diff --git a/lib/__tests__/KRadioButtonGroup.spec.js b/lib/__tests__/KRadioButtonGroup.spec.js new file mode 100644 index 000000000..0aea127ba --- /dev/null +++ b/lib/__tests__/KRadioButtonGroup.spec.js @@ -0,0 +1,96 @@ +import { mount } from '@vue/test-utils'; +import KRadioButtonGroup from '../KRadioButtonGroup.vue'; +import KRadioButton from '../KRadioButton.vue'; + +describe('KRadioButtonGroup component', () => { + beforeEach(() => { + // Mocked the userAgent because KRadioButtionGroup implements roving tabIndex only for firefox + // So these tests are testing for firefox client only + Object.defineProperty(window.navigator, 'userAgent', { + value: 'mozilla/5.0 (x11; ubuntu; linux x86_64; rv:126.0) gecko/20100101 firefox/126.0', + writable: true, + }); + }); + describe('slot', () => { + it('renders two KRadioButton', () => { + const wrapper = mount(KRadioButtonGroup, { + slots: { + default: [ + '', + '', + ], + }, + }); + expect(wrapper.findAllComponents(KRadioButton).length).toBe(2); + }); + }); + describe('Behavior Tests', () => { + it('handles keyboard navigation (focus previous/next radio)', async () => { + const wrapper = mount(KRadioButtonGroup, { + slots: { + default: [ + '', + '', + ], + }, + }); + await wrapper.vm.$nextTick(); + + const radioButtons = wrapper.findAllComponents(KRadioButton); + expect(radioButtons.length).toBe(2); + + await radioButtons.at(0).trigger('keydown', { key: 'ArrowDown' }); + expect(wrapper.vm.focusedRadioIdx).toBe(1); + expect(radioButtons.at(0).vm.tabIndex).toBe(-1); + expect(radioButtons.at(1).vm.tabIndex).toBe(0); + + await radioButtons.at(1).trigger('keydown', { key: 'ArrowUp' }); + expect(wrapper.vm.focusedRadioIdx).toBe(0); + expect(radioButtons.at(0).vm.tabIndex).toBe(0); + expect(radioButtons.at(1).vm.tabIndex).toBe(-1); + }); + it('handles click on radio correctly', async () => { + const wrapper = mount(KRadioButtonGroup, { + slots: { + default: [ + '', + '', + '', + ], + }, + }); + await wrapper.vm.$nextTick(); + const radioButtons = wrapper.findAllComponents(KRadioButton); + await radioButtons.at(2).trigger('click'); + expect(wrapper.vm.focusedRadioIdx).toBe(2); + expect(radioButtons.at(2).vm.tabIndex).toBe(0); + expect(radioButtons.at(1).vm.tabIndex).toBe(-1); + }); + it('handles enabling and disabling correctly', async () => { + const wrapper = mount(KRadioButtonGroup, { + props: { + enable: true, + }, + slots: { + default: [ + '', + '', + '', + ], + }, + }); + await wrapper.vm.$nextTick(); + const radioButtons = wrapper.findAllComponents(KRadioButton); + await radioButtons.at(2).trigger('click'); + expect(wrapper.vm.focusedRadioIdx).toBe(2); + expect(radioButtons.at(2).vm.tabIndex).toBe(0); + expect(radioButtons.at(1).vm.tabIndex).toBe(-1); + + await wrapper.setProps({ enable: false }); + await wrapper.setProps({ enable: true }); + expect(wrapper.vm.focusedRadioIdx).toBe(0); + expect(radioButtons.at(0).vm.tabIndex).toBe(0); + expect(radioButtons.at(1).vm.tabIndex).toBe(-1); + }); + }); +}); From eb9c801dbe9abf742e564c78fd81bf01f9200003 Mon Sep 17 00:00:00 2001 From: Mudit Choudhary Date: Tue, 4 Jun 2024 16:10:42 +0530 Subject: [PATCH 04/21] Add docs for KRadioButtonGroup - Add KRadioButton method description - Add KRadioButtonGroup slot and props description --- docs/pages/kradiobuttongroup.vue | 55 ++++++++++++++++++++++++++++++++ lib/KRadioButton.vue | 1 + lib/KRadioButtonGroup.vue | 5 +++ 3 files changed, 61 insertions(+) create mode 100644 docs/pages/kradiobuttongroup.vue diff --git a/docs/pages/kradiobuttongroup.vue b/docs/pages/kradiobuttongroup.vue new file mode 100644 index 000000000..1c6ede41c --- /dev/null +++ b/docs/pages/kradiobuttongroup.vue @@ -0,0 +1,55 @@ + + + + diff --git a/lib/KRadioButton.vue b/lib/KRadioButton.vue index 414c2f89d..b4cc2d8aa 100644 --- a/lib/KRadioButton.vue +++ b/lib/KRadioButton.vue @@ -224,6 +224,7 @@ }, /** * @public + * Set the tabIndex value */ setTabIndex(val) { this.tabIndex = val; diff --git a/lib/KRadioButtonGroup.vue b/lib/KRadioButtonGroup.vue index b5c2f3ca6..279cc8631 100644 --- a/lib/KRadioButtonGroup.vue +++ b/lib/KRadioButtonGroup.vue @@ -1,6 +1,7 @@