From f12597bf72f5bdface811c404555aa0081666009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=89=B3=E5=85=B5?= Date: Wed, 8 Apr 2026 09:49:24 +0800 Subject: [PATCH] fix: prevent selecting disabled items with keyboard navigation --- src/index.tsx | 13 +++++++++---- tests/index.test.tsx | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 50f36c2..323e61d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -237,15 +237,20 @@ const Segmented = React.forwardRef( // ======================= Keyboard ======================== const onOffset = (offset: number) => { - const currentIndex = segmentedOptions.findIndex( + // keep the current option and not disabled options + const validOptions = segmentedOptions.filter( + (option) => option.value === rawValue || !option.disabled, + ); + + const currentIndex = validOptions.findIndex( (option) => option.value === rawValue, ); - const total = segmentedOptions.length; + const total = validOptions.length; const nextIndex = (currentIndex + offset + total) % total; + const nextOption = validOptions[nextIndex]; - const nextOption = segmentedOptions[nextIndex]; - if (nextOption) { + if (nextOption && nextOption.value !== rawValue) { setRawValue(nextOption.value); onChange?.(nextOption.value); } diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 5b87e0a..cea8740 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -754,6 +754,33 @@ describe('Segmented keyboard navigation', () => { expect(onChange).toHaveBeenCalledWith('iOS'); }); + it('should not select a disabled option when it is the only next item', async () => { + const user = userEvent.setup(); + const onChange = jest.fn(); + const { container } = render( + , + ); + + await user.tab(); + await user.tab(); + await user.keyboard('{ArrowRight}'); + + const inputs = container.querySelectorAll( + '.rc-segmented-item-input', + ); + + expect(onChange).not.toHaveBeenCalled(); + expect(inputs[0].checked).toBe(true); + expect(inputs[1].checked).toBe(false); + }); + it('should not have focus style when clicking', async () => { const user = userEvent.setup(); const { container } = render(