diff --git a/cypress/component/Modal.cy.tsx b/cypress/component/Modal.cy.tsx
index 360b735a9e..1a88e7088c 100644
--- a/cypress/component/Modal.cy.tsx
+++ b/cypress/component/Modal.cy.tsx
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
import React, { useState } from 'react'
-import { Modal, View, Button } from '@instructure/ui'
+import { Tooltip, Modal, Button, CloseButton, View } from '@instructure/ui'
import 'cypress-real-events'
import '../support/component'
@@ -171,4 +171,192 @@ describe('', () => {
cy.get('[data-testid="modal-content"]').should('not.exist')
})
+
+ it('should not close with shouldCloseOnDocumentClick when Tooltip inside is clicked on', async () => {
+ const TestModal = () => {
+ const [open, setOpen] = useState(false)
+
+ return (
+
+
+ {
+ setOpen(false)
+ }}
+ shouldCloseOnDocumentClick
+ >
+ {
+ setOpen(false)
+ }}
+ />
+
+
+
+
+
+ )
+ }
+ cy.mount()
+
+ cy.contains('Open the Modal').click()
+
+ cy.get('[data-testid="trigger"]').then(($trigger) => {
+ const tooltipId = $trigger.attr('data-position-target')
+ const tooltip = `span[data-position-content="${tooltipId}"]`
+
+ cy.get(tooltip).should('not.be.visible')
+
+ cy.get('[data-testid="trigger"]')
+ .realHover()
+ .then(() => {
+ cy.get(tooltip).should('be.visible')
+ })
+
+ cy.get(tooltip)
+ .realClick()
+ .wait(500)
+ .then(() => {
+ cy.get(tooltip).should('be.visible')
+ cy.get('[role="dialog"]').should('be.visible')
+ })
+ })
+ })
+
+ it('should not close with shouldCloseOnDocumentClick when inside Tooltip has renderTip with HTML content', async () => {
+ const TestModal = () => {
+ const [open, setOpen] = useState(false)
+
+ return (
+
+
+
{
+ setOpen(false)
+ }}
+ shouldCloseOnDocumentClick
+ >
+ {
+ setOpen(false)
+ }}
+ />
+
+ HTML content
+
+ }
+ >
+
+
+
+
+ )
+ }
+ cy.mount()
+
+ cy.contains('Open the Modal').click()
+
+ cy.get('[data-testid="trigger"]').then(($trigger) => {
+ const tooltipId = $trigger.attr('data-position-target')
+ const tooltip = `span[data-position-content="${tooltipId}"]`
+
+ cy.get(tooltip).should('not.be.visible')
+
+ cy.get('[data-testid="trigger"]')
+ .realHover()
+ .then(() => {
+ cy.get(tooltip).should('be.visible')
+ })
+
+ cy.get(tooltip)
+ .realClick()
+ .wait(500)
+ .then(() => {
+ cy.get(tooltip).should('be.visible')
+ cy.get('[role="dialog"]').should('be.visible')
+ })
+ })
+ })
+
+ it('should not close with shouldCloseOnDocumentClick when ToolTip button is focused and Tooltip is clicked', async () => {
+ const TestModal = () => {
+ const [open, setOpen] = useState(false)
+
+ return (
+
+
+ {
+ setOpen(false)
+ }}
+ shouldCloseOnDocumentClick
+ >
+ {
+ setOpen(false)
+ }}
+ />
+ HTML content
}>
+
+
+
+
+ )
+ }
+ cy.mount()
+
+ cy.contains('Open the Modal').click()
+
+ cy.get('[data-testid="trigger"]').then(($trigger) => {
+ const tooltipId = $trigger.attr('data-position-target')
+ const tooltip = `span[data-position-content="${tooltipId}"]`
+
+ cy.get(tooltip).should('not.be.visible')
+
+ cy.get('[data-testid="trigger"]')
+ .realClick()
+ .then(() => {
+ cy.get(tooltip).should('be.visible')
+ cy.get('[data-testid="trigger"]')
+ .should('have.focus')
+ .then(() => {
+ cy.get(tooltip)
+ .realClick()
+ .wait(500)
+ .then(() => {
+ cy.get('[role="dialog"]').should('be.visible')
+ })
+ })
+ })
+ })
+ })
})
diff --git a/packages/ui-a11y-utils/src/FocusRegion.ts b/packages/ui-a11y-utils/src/FocusRegion.ts
index ab12e7a6f8..3309a1ab04 100644
--- a/packages/ui-a11y-utils/src/FocusRegion.ts
+++ b/packages/ui-a11y-utils/src/FocusRegion.ts
@@ -28,7 +28,8 @@ import {
contains,
addEventListener,
ownerDocument,
- findTabbable
+ findTabbable,
+ canUseDOM
} from '@instructure/ui-dom-utils'
import { uid } from '@instructure/uid'
import { logError as error } from '@instructure/console'
@@ -96,7 +97,13 @@ 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._contextContainsTarget &&
+ //this prevents clicking on Tooltip from closing the parent dialog
+ !(
+ canUseDOM &&
+ this._documentClickTarget instanceof HTMLElement &&
+ this._documentClickTarget.closest('[role="tooltip"]')
+ )
) {
this.handleDismiss(event, true)
}