-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix focus loss from Combobox.Input
when disabled option clicked
#3008
Changes from all commits
ea2b62f
2285959
172de96
eb0f5df
2516a8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,7 +252,7 @@ export async function rawClick( | |
if (!cancelled) { | ||
let next: HTMLElement | null = element as HTMLElement | null | ||
while (next !== null) { | ||
if (next.matches(focusableSelector)) { | ||
if (next.matches(focusableSelectorWithNegativeTabindex)) { | ||
next.focus() | ||
break | ||
} | ||
|
@@ -463,9 +463,7 @@ function focusNext(event: Partial<KeyboardEvent>) { | |
return innerFocusNext() | ||
} | ||
|
||
// Credit: | ||
// - https://stackoverflow.com/a/30753870 | ||
let focusableSelector = [ | ||
let _focusableSelector = [ | ||
'[contentEditable=true]', | ||
'[tabindex]', | ||
'a[href]', | ||
|
@@ -476,6 +474,10 @@ let focusableSelector = [ | |
'select:not([disabled])', | ||
'textarea:not([disabled])', | ||
] | ||
|
||
// Credit: | ||
// - https://stackoverflow.com/a/30753870 | ||
let focusableSelector = _focusableSelector | ||
.map( | ||
process.env.NODE_ENV === 'test' | ||
? // TODO: Remove this once JSDOM fixes the issue where an element that is | ||
|
@@ -486,6 +488,14 @@ let focusableSelector = [ | |
) | ||
.join(',') | ||
|
||
let focusableSelectorWithNegativeTabindex = _focusableSelector | ||
.map( | ||
process.env.NODE_ENV === 'test' | ||
? (selector) => `${selector}:not([style*='display: none'])` | ||
: (selector) => selector | ||
) | ||
.join(',') | ||
Comment on lines
+491
to
+497
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An element with |
||
|
||
function getFocusableElements(container = document.body) { | ||
if (!container) return [] | ||
return Array.from(container.querySelectorAll(focusableSelector)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,16 +218,14 @@ function mergeProps(...listOfProps: Record<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?.()] | ||
} | ||
} | ||
Comment on lines
+221
to
+228
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed it in the same way as the |
||
} | ||
|
||
// Merge event handlers | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set
tabIndex=-1
forCombobox.Option
when it is disabled.Moved
data.inputRef.current?.focus({ preventScroll: true })
fromhandleClick
tohandleFocus
and ensured it is called even when the option is disabled.The reason for moving it into
handleFocus
is that theonClick
event handler for disabled options is ignored by themergePropsAdvanced
function.