Improve cancellation of events when using disabled or aria-disabled attributes (#2890)
* only cancel certain events when disabled The initial idea was that whenever an element had the `disabled` or `aria-disabled` prop/attribute that we were going to remove all the event listeners. However, this is not ideal because in some scenario's we were actually explicitly adding `onClick()` listeners (for `<a>` elements) to `e.preventDefault()` when the link was marked as "disabled" to prevent it executing the actual link click. This commit will allow all defined listeners as-is, however, if you are using one of the following event listeners: - `onClick` - `onPointerUp` - `onPointerDown` - `onMouseUp` - `onMouseDown` - `onKeyUp` - `onKeyPress` - `onKeyDown` Then we will replace it with `(e) => e.preventDefault()` instead. This way we are still invoking your own listeners, but are explicitly calling `e.preventDefault()` on listeners that should not be executed in the first place when an element is `disabled`. * update CHANGELOG.md * update CHANGELOG.md
This commit is contained in:
@@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Allow horizontal scrolling when scroll locking ([bdf4f8e](https://github.com/tailwindlabs/headlessui/commit/bdf4f8e32358485dd9c437c0d631309250ee5624))
|
||||
- Allow horizontal scrolling inside the `Dialog` component ([#2889](https://github.com/tailwindlabs/headlessui/pull/2889))
|
||||
- Improve cancellation of events when using `disabled` or `aria-disabled` attributes ([#2890](https://github.com/tailwindlabs/headlessui/pull/2890))
|
||||
|
||||
## [2.0.0-alpha.1] - 2023-12-20
|
||||
|
||||
|
||||
@@ -318,16 +318,14 @@ function mergePropsAdvanced(...listOfProps: Props<any, any>[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// Do not attach any event handlers when there is a `disabled` or `aria-disabled` prop set.
|
||||
// Ensure event listeners are not called if `disabled` or `aria-disabled` is true
|
||||
if (target.disabled || target['aria-disabled']) {
|
||||
return Object.assign(
|
||||
target,
|
||||
// Set all event listeners that we collected to `undefined`. This is
|
||||
// important because of the `cloneElement` from above, which merges the
|
||||
// existing and new props, they don't just override therefore we have to
|
||||
// explicitly nullify them.
|
||||
Object.fromEntries(Object.keys(eventHandlers).map((eventName) => [eventName, undefined]))
|
||||
)
|
||||
for (let eventName in eventHandlers) {
|
||||
// Prevent default events for `onClick`, `onMouseDown`, `onKeyDown`, etc.
|
||||
if (/^(on(?:Click|Pointer|Mouse|Key)(?:Down|Up|Press)?)$/.test(eventName)) {
|
||||
eventHandlers[eventName] = [(e: any) => e?.preventDefault?.()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge event handlers
|
||||
|
||||
Reference in New Issue
Block a user