From 33a5893e4f203e76f50e18d98ddec12fc0eb3b75 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 21 Dec 2023 00:09:08 +0100 Subject: [PATCH] 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 `` 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 --- packages/@headlessui-react/CHANGELOG.md | 3 ++- packages/@headlessui-react/src/utils/render.ts | 16 +++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index f61b449..414084e 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -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 diff --git a/packages/@headlessui-react/src/utils/render.ts b/packages/@headlessui-react/src/utils/render.ts index 304dde4..56895f6 100644 --- a/packages/@headlessui-react/src/utils/render.ts +++ b/packages/@headlessui-react/src/utils/render.ts @@ -318,16 +318,14 @@ function mergePropsAdvanced(...listOfProps: Props[]) { } } - // 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