From aa886763eee3f4f69d8f49e909521777073b91f5 Mon Sep 17 00:00:00 2001 From: krzysztofczech Date: Tue, 3 Dec 2024 11:53:40 +0100 Subject: [PATCH] fix(ui-a11y-utils): fix focus region missing mouse down target --- packages/ui-a11y-utils/src/FocusRegion.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/ui-a11y-utils/src/FocusRegion.ts b/packages/ui-a11y-utils/src/FocusRegion.ts index 4dc70abbe7..0f18e6c072 100644 --- a/packages/ui-a11y-utils/src/FocusRegion.ts +++ b/packages/ui-a11y-utils/src/FocusRegion.ts @@ -45,8 +45,7 @@ class FocusRegion { private readonly _id: string private _listeners: ReturnType[] = [] private _active = false - private _documentClickTarget: Node | null = null - private _contextContainsTarget = false + private _documentMouseDownTarget: Node | null = null constructor(element: Element | Node | null, options: FocusRegionOptions) { this._options = options || { @@ -83,11 +82,8 @@ class FocusRegion { } captureDocumentMousedown = (event: React.MouseEvent) => { - this._documentClickTarget = event.target as Node - this._contextContainsTarget = contains( - this._contextElement, - this._documentClickTarget - ) + // FocusRegion can be activated after mousedown but before click so this is not guaranteed to fire. + this._documentMouseDownTarget = event.target as Node } handleDocumentClick = (event: React.PointerEvent) => { @@ -95,12 +91,21 @@ class FocusRegion { this._options.shouldCloseOnDocumentClick && event.button === 0 && event.detail > 0 && // if event.detail is 0 then this is a keyboard and not a mouse press - !this._contextContainsTarget + this.shouldDismissOnClick(event.target as Node) ) { this.handleDismiss(event, true) } } + shouldDismissOnClick = (clickTarget: Node) => { + // don't dismiss when click stared within the region but ended outside eg. when user is selecting a text. + // don't dismiss when _documentMouseDownTarget is null. eg. when the region was activated after mousedown but before click. + return ( + !contains(this._contextElement, this._documentMouseDownTarget) && + !contains(this._contextElement, clickTarget) + ) + } + handleFrameClick = (event: React.MouseEvent, frame: HTMLIFrameElement) => { if (!contains(this._contextElement, frame)) { // dismiss if frame is not within the region