Skip to content

Commit

Permalink
Attempt form submission when pressing Enter on Checkbox component (
Browse files Browse the repository at this point in the history
…#2962)

* attempt to submit form when pressing `Enter` on the `Checkbox` component

* add test to verify form submissions when pressing enter works

* update changelog
  • Loading branch information
RobinMalfait authored Feb 2, 2024
1 parent edbcb81 commit da94b80
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
1 change: 1 addition & 0 deletions packages/@headlessui-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use `isFocused` instead of `isFocusVisible` for `Input` and `Textarea` components ([#2940](https://github.com/tailwindlabs/headlessui/pull/2940))
- Ensure `children` prop of `Field` component can be a render prop ([#2941](https://github.com/tailwindlabs/headlessui/pull/2941))
- Add `hidden` attribute to internal `<Hidden />` component when the `Features.Hidden` feature is used ([#2955](https://github.com/tailwindlabs/headlessui/pull/2955))
- Attempt form submission when pressing `Enter` on `Checkbox` component ([#2962](https://github.com/tailwindlabs/headlessui/pull/2962))

## [2.0.0-alpha.4] - 2024-01-03

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,47 @@ describe.each([
})
)
})

describe('Form submissions', () => {
it('should be possible to use in an uncontrolled way', async () => {
let handleSubmission = jest.fn()

render(
<form
onSubmit={(e) => {
e.preventDefault()
handleSubmission(Object.fromEntries(new FormData(e.target as HTMLFormElement)))
}}
>
<Checkbox name="notifications" />
</form>
)

// Focus the checkbox
await focus(getCheckbox())

// Submit
await press(Keys.Enter)

// No values
expect(handleSubmission).toHaveBeenLastCalledWith({})

// Toggle
await click(getCheckbox())

// Submit
await press(Keys.Enter)

// Notifications should be on
expect(handleSubmission).toHaveBeenLastCalledWith({ notifications: 'on' })

// Toggle
await click(getCheckbox())

// Submit
await press(Keys.Enter)

// Notifications should be off (or in this case, non-existant)
expect(handleSubmission).toHaveBeenLastCalledWith({})
})
})
22 changes: 13 additions & 9 deletions packages/@headlessui-react/src/components/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FormFields } from '../../internal/form-fields'
import { useProvidedId } from '../../internal/id'
import type { Props } from '../../types'
import { isDisabledReactIssue7711 } from '../../utils/bugs'
import { attemptSubmit } from '../../utils/form'
import {
forwardRefWithAs,
mergeProps,
Expand Down Expand Up @@ -110,20 +111,22 @@ function CheckboxFn<TTag extends ElementType = typeof DEFAULT_CHECKBOX_TAG, TTyp

let handleClick = useEvent((event: ReactMouseEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()
event.preventDefault()
toggle()
})

let handleKeyDown = useEvent((event: ReactKeyboardEvent) => {
if (isDisabledReactIssue7711(event.currentTarget)) return event.preventDefault()

switch (event.key) {
case Keys.Space:
event.preventDefault()
toggle()
break
let handleKeyUp = useEvent((event: ReactKeyboardEvent<HTMLButtonElement>) => {
if (event.key === Keys.Space) {
event.preventDefault()
toggle()
} else if (event.key === Keys.Enter) {
attemptSubmit(event.currentTarget)
}
})

// This is needed so that we can "cancel" the click event when we use the `Enter` key on a button.
let handleKeyPress = useEvent((event: ReactKeyboardEvent<HTMLElement>) => event.preventDefault())

let { isFocusVisible: focus, focusProps } = useFocusRing({ autoFocus: props.autoFocus ?? false })
let { isHovered: hover, hoverProps } = useHover({ isDisabled: disabled ?? false })
let { pressed: active, pressProps } = useActivePress({ disabled: disabled ?? false })
Expand All @@ -139,7 +142,8 @@ function CheckboxFn<TTag extends ElementType = typeof DEFAULT_CHECKBOX_TAG, TTyp
'aria-disabled': disabled ? true : undefined,
indeterminate: indeterminate ? 'true' : undefined,
tabIndex: 0,
onKeyDown: disabled ? undefined : handleKeyDown,
onKeyUp: disabled ? undefined : handleKeyUp,
onKeyPress: disabled ? undefined : handleKeyPress,
onClick: disabled ? undefined : handleClick,
},
focusProps,
Expand Down

0 comments on commit da94b80

Please sign in to comment.