Skip to content

Commit 533ee70

Browse files
authored
fix: prevent selecting disabled items with keyboard navigation (#326)
1 parent 0a35404 commit 533ee70

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

src/index.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,20 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
237237

238238
// ======================= Keyboard ========================
239239
const onOffset = (offset: number) => {
240-
const currentIndex = segmentedOptions.findIndex(
240+
// keep the current option and not disabled options
241+
const validOptions = segmentedOptions.filter(
242+
(option) => option.value === rawValue || !option.disabled,
243+
);
244+
245+
const currentIndex = validOptions.findIndex(
241246
(option) => option.value === rawValue,
242247
);
243248

244-
const total = segmentedOptions.length;
249+
const total = validOptions.length;
245250
const nextIndex = (currentIndex + offset + total) % total;
251+
const nextOption = validOptions[nextIndex];
246252

247-
const nextOption = segmentedOptions[nextIndex];
248-
if (nextOption) {
253+
if (nextOption && nextOption.value !== rawValue) {
249254
setRawValue(nextOption.value);
250255
onChange?.(nextOption.value);
251256
}

tests/index.test.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,33 @@ describe('Segmented keyboard navigation', () => {
754754
expect(onChange).toHaveBeenCalledWith('iOS');
755755
});
756756

757+
it('should not select a disabled option when it is the only next item', async () => {
758+
const user = userEvent.setup();
759+
const onChange = jest.fn();
760+
const { container } = render(
761+
<Segmented
762+
options={[
763+
{ label: 'Enabled', value: 'enabled' },
764+
{ label: 'Disabled', value: 'disabled', disabled: true },
765+
]}
766+
defaultValue="enabled"
767+
onChange={onChange}
768+
/>,
769+
);
770+
771+
await user.tab();
772+
await user.tab();
773+
await user.keyboard('{ArrowRight}');
774+
775+
const inputs = container.querySelectorAll<HTMLInputElement>(
776+
'.rc-segmented-item-input',
777+
);
778+
779+
expect(onChange).not.toHaveBeenCalled();
780+
expect(inputs[0].checked).toBe(true);
781+
expect(inputs[1].checked).toBe(false);
782+
});
783+
757784
it('should not have focus style when clicking', async () => {
758785
const user = userEvent.setup();
759786
const { container } = render(

0 commit comments

Comments
 (0)