diff --git a/packages/react-aria-components/test/Checkbox.test.js b/packages/react-aria-components/test/Checkbox.test.js index 91e467f98a7..d6ef0d521b6 100644 --- a/packages/react-aria-components/test/Checkbox.test.js +++ b/packages/react-aria-components/test/Checkbox.test.js @@ -385,4 +385,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 f12aece756d..e02f3e17c7a 100644 --- a/packages/react-aria-components/test/RadioGroup.test.js +++ b/packages/react-aria-components/test/RadioGroup.test.js @@ -739,4 +739,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 cc1bbce8031..28dedce94b2 100644 --- a/packages/react-aria-components/test/Switch.test.js +++ b/packages/react-aria-components/test/Switch.test.js @@ -359,4 +359,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/radio/useRadio.ts b/packages/react-aria/src/radio/useRadio.ts index 3bdb69b32b9..827c43b19b0 100644 --- a/packages/react-aria/src/radio/useRadio.ts +++ b/packages/react-aria/src/radio/useRadio.ts @@ -118,6 +118,10 @@ export function useRadio(props: AriaRadioProps, state: RadioGroupState, ref: Ref } }); + // Let the hidden radio input handle keyboard events natively so Enter can + // submit forms like a native radio control. + delete labelProps.onKeyDown; + let {focusableProps} = useFocusable(mergeProps(props, { onFocus: () => state.setLastFocusedValue(value) }), ref); diff --git a/packages/react-aria/src/toggle/useToggle.ts b/packages/react-aria/src/toggle/useToggle.ts index d35be1ada26..487348b98fd 100644 --- a/packages/react-aria/src/toggle/useToggle.ts +++ b/packages/react-aria/src/toggle/useToggle.ts @@ -161,6 +161,10 @@ export function useToggle(props: AriaToggleProps, state: ToggleState, ref: RefOb isDisabled: isDisabled || isReadOnly }); + // Let the hidden input handle keyboard events natively so Enter can + // submit forms like a native checkbox/switch control. + delete labelProps.onKeyDown; + let {focusableProps} = useFocusable(props, ref); let interactions = mergeProps(pressProps, focusableProps); let domProps = filterDOMProps(props, {labelable: true});