-
Notifications
You must be signed in to change notification settings - Fork 982
[Dialog][Popover][DropdownMenu][ContextMenu] Adjust non-modal auto focus behaviour #799
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
Conversation
❤️ |
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.
some nits, but not gonna hold up the PR for them. Rest looks good 👍
packages/react/dialog/src/Dialog.tsx
Outdated
onCloseAutoFocus={(event) => { | ||
props.onCloseAutoFocus?.(event); | ||
const userPrevented = event.defaultPrevented; | ||
|
||
if (!userPrevented) { | ||
event.preventDefault(); | ||
if (!isInteractOutsideRef.current) context.triggerRef.current?.focus(); | ||
} | ||
|
||
isInteractOutsideRef.current = false; | ||
}} |
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.
Was there a reason we didn't go with this?
onCloseAutoFocus={(event) => { | |
props.onCloseAutoFocus?.(event); | |
const userPrevented = event.defaultPrevented; | |
if (!userPrevented) { | |
event.preventDefault(); | |
if (!isInteractOutsideRef.current) context.triggerRef.current?.focus(); | |
} | |
isInteractOutsideRef.current = false; | |
}} | |
onCloseAutoFocus={(event) => { | |
props.onCloseAutoFocus?.(event); | |
if (!event.defaultPrevented && !isInteractOutsideRef.current) { | |
context.triggerRef.current?.focus(); | |
} | |
isInteractOutsideRef.current = false; | |
event.preventDefault(); | |
}} |
The current one confused me a bit because preventDefault
is always happening either way. Either they are doing it or we are so we may as well event.preventDefault()
all the time. It didn't make sense why that had to be part of the conditional.
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.
In fact, shouldn't we only be preventing default if we're focusing ourselves? so it would be in both conditionals:
onCloseAutoFocus={(event) => {
props.onCloseAutoFocus?.(event);
if (!event.defaultPrevented && !isInteractOutsideRef.current) {
event.preventDefault();
context.triggerRef.current?.focus();
}
isInteractOutsideRef.current = false;
}}
?
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.
Mainly for the ordering reason in Benoit's comment #799 (comment) if we take it out of the condition then we need to ensure it comes after.
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.
In fact, shouldn't we only be preventing default if we're focusing ourselves?
Ah I didn't see this comment before I added mine, yeah I think you're right!
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.
No, that's not right, we need to prevent all the time not just when we're focusing something manually. Like I explained here: #799 (comment)
I understand we need to do it in ALL cases because either:
- we don't want to run any focus at all (ie. you've clicked somewhere outside, so natural focus should occur)
- we want explicit focus to trigger so we prevent the default close auto focus
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.
@benoitgrelard is on the money here, it always needs to happen in non-modal to avoid focus fighting on outside clicks etc. fb6e32c this whole thing got a little confusing after a while 😅
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.
Ah of course... wow, yeah, my head is spinning 😅
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.
On the whole "coming after" thing. What's wrong with that? In the olden days this was actually the recommended place to put it to ensure progressive enhancement didn't break things if there was a JS error in the handling logic. I actually prefer it at the end for that reason.
See this example where when JS fails, the app still works if the event is prevented at the end https://codepen.io/jjenzz/pen/BaRrOdX
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.
Code-wise looks good to me but I'll leave it to Benoit to make sure it's all good behaviour-wise since he has a much deeper understanding than me here 😅
@jjenzz – Me and @benoitgrelard had a call on this and made some readability changes plus reverted some wrong assumptions I had with the last round of changes. Going to merge now and we can discuss more in the main modality branch if needed. |
…cus behaviour (#799) * Adjust non-modal auto focus behaviour * Code style * Explicitly handle ref clearing * Refine ref clearing * Simplify handler composition in non-modal * Feedback * Revert auto focus cancellation * Improve focus handling readability * [ContextMenu] Adjust non-modal focus handling
) * [FocusScope] Update API for modality changes (#698) * [FocusScope] Update API for modality changes * Address PR feedback * PR feedback * [Dialog] Add support for non-modal dialogs (#699) * [Dialog] Add support for non-modal dialogs * PR feedback * [Dialog] Fix non modal toggle on close (#757) * [AlertDialog] Explicit modality, prevent pointer dismiss (#758) * [AlertDialog] Don't compose onPointerDownOutside (#759) * [AlertDialog] Don't compose onPointerDownOutside * Code style * [Popover] Add support for modality (#751) * [Popover] Add support for modality * Modality scroll behaviour, default to non modal * Adjust for focus close in chromatic stories * Fix toggle when closing non modal * [Dialog][Popover] Update interact description * [Popover] Restore `checkForDefaultPrevented` (#764) * [DropdownMenu][ContextMenu] Add modality support (#768) * [Menu] Support modality * [DropdownMenu] Expose modality * [ContextMenu] Expose modality * [DropdownMenu] `mouseDown` -> `pointerDown` * [Menu] disableOutsidePointerEvents only when open * [DropdownMenu][Popover][Dialog] Apply explicit trigger auto focus (#771) * Explicit trigger focus * Simplify handling where possible * Code style, remove redundant check * [Popover] Revert `onEscapeKeyDown` default check * Versions * [Dialog][Popover][DropdownMenu][ContextMenu] Adjust non-modal auto focus behaviour (#799) * Adjust non-modal auto focus behaviour * Code style * Explicitly handle ref clearing * Refine ref clearing * Simplify handler composition in non-modal * Feedback * Revert auto focus cancellation * Improve focus handling readability * [ContextMenu] Adjust non-modal focus handling * [ContextMenu][Dialog][DropdownMenu][ContextMenu] Adjust ref naming (#805) * Adjust ref naming * [ContextMenu] Move modal condition Co-authored-by: Andy Hook <[email protected]>
Previously non-modal auto focus was not covering use of the close button. This change applies auto focus for all interactions except when pointer down outside.