From 34040a7bf793d927ac4b1e2141edd8f406cf9608 Mon Sep 17 00:00:00 2001 From: Ferit Date: Thu, 22 Oct 2026 06:52:35 +0300 Subject: [PATCH 1/2] fix: prevent default scrolling on arrow navigation and handle RTL direction --- src/index.tsx | 11 ++++++++++- tests/index.test.tsx | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 017aebc..15b3002 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -254,13 +254,22 @@ const Segmented = React.forwardRef( }; const handleKeyDown = (event: React.KeyboardEvent) => { + const isRtl = direction === 'rtl'; switch (event.key) { case 'ArrowLeft': + event.preventDefault(); + onOffset(isRtl ? 1 : -1); + break; + case 'ArrowRight': + event.preventDefault(); + onOffset(isRtl ? -1 : 1); + break; case 'ArrowUp': + event.preventDefault(); onOffset(-1); break; - case 'ArrowRight': case 'ArrowDown': + event.preventDefault(); onOffset(1); break; } diff --git a/tests/index.test.tsx b/tests/index.test.tsx index a686201..4769be4 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -719,6 +719,31 @@ describe('Segmented keyboard navigation', () => { expect(onChange).toHaveBeenCalledWith('Web'); }); + it('should handle arrow navigation in RTL mode and prevent default', async () => { + const user = userEvent.setup(); + const onChange = jest.fn(); + render( + , + ); + + await user.tab(); + await user.tab(); + + // In RTL, ArrowRight moves to previous item + await user.keyboard('{ArrowRight}'); + expect(onChange).toHaveBeenCalledWith('Web'); + + onChange.mockClear(); + + // In RTL, ArrowLeft moves to next item + await user.keyboard('{ArrowLeft}'); + expect(onChange).toHaveBeenCalledWith('iOS'); + }); + it('should skip Tab navigation when disabled', async () => { const user = userEvent.setup(); const { container } = render( From 0ce8176a839997f7f640c697dbb1fd85f6bc5f3b Mon Sep 17 00:00:00 2001 From: Ferit Date: Tue, 27 Oct 2026 01:24:38 +0200 Subject: [PATCH 2/2] fix: focus the selected option on arrow navigation --- src/index.tsx | 4 ++++ tests/index.test.tsx | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 15b3002..d1797f5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -248,6 +248,10 @@ const Segmented = React.forwardRef( const nextOption = validOptions[nextIndex]; if (nextOption && nextOption.value !== rawValue) { + const optionIndex = segmentedOptions.indexOf(nextOption); + containerRef.current + ?.querySelectorAll(`input.${prefixCls}-item-input`) + [optionIndex]?.focus(); setRawValue(nextOption.value); onChange?.(nextOption.value); } diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 4769be4..8165dde 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -722,8 +722,9 @@ describe('Segmented keyboard navigation', () => { it('should handle arrow navigation in RTL mode and prevent default', async () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( + const { getAllByRole } = render( { await user.keyboard('{ArrowRight}'); expect(onChange).toHaveBeenCalledWith('Web'); + expect(getAllByRole('radio')[2]).toHaveFocus(); + onChange.mockClear(); // In RTL, ArrowLeft moves to next item await user.keyboard('{ArrowLeft}'); expect(onChange).toHaveBeenCalledWith('iOS'); + expect(getAllByRole('radio')[0]).toHaveFocus(); }); it('should skip Tab navigation when disabled', async () => {