diff --git a/packages/react-aria-components/test/Checkbox.test.js b/packages/react-aria-components/test/Checkbox.test.js index 4d7b0991c02..f87ce806420 100644 --- a/packages/react-aria-components/test/Checkbox.test.js +++ b/packages/react-aria-components/test/Checkbox.test.js @@ -465,4 +465,20 @@ describe.each(['Checkbox', 'CheckboxField'])('%s', comp => { expect(onBlur).not.toHaveBeenCalled(); expect(onFocus).not.toHaveBeenCalled(); }); + + it('should support implicit form submission from a focused checkbox on Enter', async () => { + let onSubmit = jest.fn(e => e.preventDefault()); + let {getByRole} = render( +
+ ); + + let checkbox = getByRole('checkbox'); + await user.click(checkbox); + await user.keyboard('{Enter}'); + + expect(onSubmit).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/react-aria-components/test/RadioGroup.test.js b/packages/react-aria-components/test/RadioGroup.test.js index 01b314f58e6..b0eb5a61ab1 100644 --- a/packages/react-aria-components/test/RadioGroup.test.js +++ b/packages/react-aria-components/test/RadioGroup.test.js @@ -849,4 +849,24 @@ describe.each(['RadioGroup', 'RadioField'])('%s', comp => { expect(onFocusB).toHaveBeenCalledTimes(1); expect(onBlurA).toHaveBeenCalledTimes(1); }); + + it('should support implicit form submission from a focused radio on Enter', async () => { + let onSubmit = jest.fn(e => e.preventDefault()); + let {getAllByRole} = render( + + ); + + let radio = getAllByRole('radio')[0]; + await user.click(radio); + await user.keyboard('{Enter}'); + + expect(onSubmit).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/react-aria-components/test/Switch.test.js b/packages/react-aria-components/test/Switch.test.js index 4bfd17e262c..5433f99d85d 100644 --- a/packages/react-aria-components/test/Switch.test.js +++ b/packages/react-aria-components/test/Switch.test.js @@ -420,4 +420,20 @@ describe.each(['Switch', 'SwitchField'])('%s', comp => { expect(checkbox).not.toHaveAttribute('aria-describedby'); }); } + + it('should support implicit form submission from a focused switch on Enter', async () => { + let onSubmit = jest.fn(e => e.preventDefault()); + let {getByRole} = render( + + ); + + let s = getByRole('switch'); + await user.click(s); + await user.keyboard('{Enter}'); + + expect(onSubmit).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/react-aria/src/interactions/usePress.ts b/packages/react-aria/src/interactions/usePress.ts index 5e88c3b25af..5cf946f0f8e 100644 --- a/packages/react-aria/src/interactions/usePress.ts +++ b/packages/react-aria/src/interactions/usePress.ts @@ -1163,6 +1163,10 @@ function shouldPreventDefaultUp(target: Element) { function shouldPreventDefaultKeyboard(target: Element, key: string) { if (target instanceof HTMLInputElement) { + if (key === 'Enter' && (target.type === 'checkbox' || target.type === 'radio')) { + // Enter on a checkbox or radio should do an implicit form submission, but not toggle the input. + return false; + } return !isValidInputKey(target, key); } diff --git a/packages/react-aria/test/interactions/usePress.test.js b/packages/react-aria/test/interactions/usePress.test.js index 2ac25bcc4d8..ec848c7467f 100644 --- a/packages/react-aria/test/interactions/usePress.test.js +++ b/packages/react-aria/test/interactions/usePress.test.js @@ -3315,7 +3315,7 @@ describe('usePress', function () { fireEvent.keyDown(el, {key: 'Enter'}); fireEvent.keyUp(el, {key: 'Enter'}); - // Enter key handled should do nothing on a checkbox + // Enter key handled should not result in a press event on a checkbox expect(events).toEqual([]); let allow = fireEvent.keyDown(el, {key: ' '});