diff --git a/change/@fluentui-react-popover-ca31294d-f8a3-4d50-bb6d-0d42a16bd4e2.json b/change/@fluentui-react-popover-ca31294d-f8a3-4d50-bb6d-0d42a16bd4e2.json
new file mode 100644
index 0000000000000..e4e1eb798040b
--- /dev/null
+++ b/change/@fluentui-react-popover-ca31294d-f8a3-4d50-bb6d-0d42a16bd4e2.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "fix: Use role=complementary for Popovers without focus traps",
+ "packageName": "@fluentui/react-popover",
+ "email": "lingfangao@hotmail.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/react-popover/e2e/Popover.e2e.ts b/packages/react-popover/e2e/Popover.e2e.ts
index 957d17cd29b00..ee3ae819b1698 100644
--- a/packages/react-popover/e2e/Popover.e2e.ts
+++ b/packages/react-popover/e2e/Popover.e2e.ts
@@ -1,5 +1,6 @@
const popoverTriggerSelector = '[aria-haspopup]';
-const popoverContentSelector = '[role="dialog"]';
+const popoverContentSelector = '[role="complementary"]';
+const popoverInteractiveContentSelector = '[role="dialog"]';
const popoverStoriesTitle = 'Components/Popover';
const popoverDefaultStory = 'Default';
@@ -95,21 +96,21 @@ describe('Popover', () => {
});
it('should dismiss all nested popovers on outside click', () => {
- cy.get('body').click('bottomRight').get(popoverContentSelector).should('not.exist');
+ cy.get('body').click('bottomRight').get(popoverInteractiveContentSelector).should('not.exist');
});
it('should not dismiss when clicking on nested content', () => {
- cy.contains('Second nested button').click().get(popoverContentSelector).should('have.length', 3);
+ cy.contains('Second nested button').click().get(popoverInteractiveContentSelector).should('have.length', 3);
});
it('should dismiss child popovers when clicking on parents', () => {
cy.contains('First nested button')
.click()
- .get(popoverContentSelector)
+ .get(popoverInteractiveContentSelector)
.should('have.length', 2)
.contains('Root button')
.click()
- .get(popoverContentSelector)
+ .get(popoverInteractiveContentSelector)
.should('have.length', 1);
});
@@ -119,22 +120,22 @@ describe('Popover', () => {
cy.get(secondNestedTriggerSelector)
.eq(1)
.click()
- .get(popoverContentSelector)
+ .get(popoverInteractiveContentSelector)
.should('have.length', 3)
.get(secondNestedTriggerSelector)
.eq(0)
.click()
- .get(popoverContentSelector)
+ .get(popoverInteractiveContentSelector)
.should('have.length', 3);
});
it('should dismiss each popover in the stack with Escape keydown', () => {
cy.focused().realPress('Escape');
- cy.get(popoverContentSelector).should('have.length', 2);
+ cy.get(popoverInteractiveContentSelector).should('have.length', 2);
cy.focused().realPress('Escape');
- cy.get(popoverContentSelector).should('have.length', 1);
+ cy.get(popoverInteractiveContentSelector).should('have.length', 1);
cy.focused().realPress('Escape');
- cy.get(popoverContentSelector).should('not.exist');
+ cy.get(popoverInteractiveContentSelector).should('not.exist');
});
});
diff --git a/packages/react-popover/src/components/PopoverSurface/PopoverSurface.test.tsx b/packages/react-popover/src/components/PopoverSurface/PopoverSurface.test.tsx
index 1ad7065026070..823c224ff2902 100644
--- a/packages/react-popover/src/components/PopoverSurface/PopoverSurface.test.tsx
+++ b/packages/react-popover/src/components/PopoverSurface/PopoverSurface.test.tsx
@@ -70,4 +70,22 @@ describe('PopoverSurface', () => {
// Assert
expect(getByTestId(testid).getAttribute('aria-modal')).toEqual('true');
});
+
+ it('should set role dialog if focus trap is active', () => {
+ // Arrange
+ mockPopoverContext({ open: true, trapFocus: true });
+ const { queryByRole } = render(