diff --git a/change/@fluentui-web-components-c799e352-175a-41e3-8338-7e785f5ea828.json b/change/@fluentui-web-components-c799e352-175a-41e3-8338-7e785f5ea828.json new file mode 100644 index 00000000000000..22b859d0d7ba80 --- /dev/null +++ b/change/@fluentui-web-components-c799e352-175a-41e3-8338-7e785f5ea828.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "avoid dialog from focusing on non-active tab upon showing", + "packageName": "@fluentui/web-components", + "email": "machi@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/web-components/src/dialog/dialog.spec.ts b/packages/web-components/src/dialog/dialog.spec.ts index 967a655033e40e..893b14868c0d9b 100644 --- a/packages/web-components/src/dialog/dialog.spec.ts +++ b/packages/web-components/src/dialog/dialog.spec.ts @@ -1,6 +1,8 @@ import type { Locator } from '@playwright/test'; import { expect, test } from '../../test/playwright/index.js'; import { tagName as DialogBodyTagName } from '../dialog-body/dialog-body.options.js'; +import { tagName as TabTagName } from '../tab/tab.options.js'; +import { tagName as TablistTagName } from '../tablist/tablist.options.js'; import type { Dialog } from './dialog.js'; import { tagName } from './dialog.options.js'; @@ -383,4 +385,43 @@ test.describe('Dialog', () => { await expect(content).toBeHidden(); }); + + test.describe('opening focus', () => { + test.use({ + tagName, + waitFor: [DialogBodyTagName, TablistTagName, TabTagName], + }); + + test('should not change tablist’s `activeid` attribute', async ({ fastPage }) => { + const { element } = fastPage; + const content = element.locator('#content'); + const tablist = element.locator(TablistTagName); + + await fastPage.setTemplate({ + innerHTML: /* html */ ` + <${DialogBodyTagName} id="content"> + <${TablistTagName} activeid="tab2"> + <${TabTagName} id="tab1">tab 1 + <${TabTagName} id="tab2">tab 2 + + + `, + }); + + await element.evaluate((node: Dialog) => { + node.show(); + }); + + await expect(content).toBeVisible(); + await expect(tablist).toHaveAttribute('activeid', 'tab2'); + + await element.evaluate((node: Dialog) => { + node.hide(); + node.show(); + }); + + await expect(content).toBeVisible(); + await expect(tablist).toHaveAttribute('activeid', 'tab2'); + }); + }); }); diff --git a/packages/web-components/src/dialog/dialog.stories.ts b/packages/web-components/src/dialog/dialog.stories.ts index e9df63d8ca5b07..3ff55ed1a97e7a 100644 --- a/packages/web-components/src/dialog/dialog.stories.ts +++ b/packages/web-components/src/dialog/dialog.stories.ts @@ -399,3 +399,18 @@ export const ScrollingLongContent: Story = { }, ], }; + +export const WithTablist: Story = { + args: { + ariaLabel: 'With Tablist', + titleSlottedContent: () => html`

With Tablist

`, + closeSlottedContent: () => html``, + slottedContent: () => html` + + tab 1 + tab 2 + tab 3 + + `, + }, +}; diff --git a/packages/web-components/src/dialog/dialog.template.ts b/packages/web-components/src/dialog/dialog.template.ts index 018eae02fa1a65..2a4991d760aab5 100644 --- a/packages/web-components/src/dialog/dialog.template.ts +++ b/packages/web-components/src/dialog/dialog.template.ts @@ -3,6 +3,11 @@ import type { Dialog } from './dialog.js'; /** * Template for the Dialog component + * + * Note: The empty `
` element above the `` element is + * for working around a dialog focus issue, learn more at + * https://github.com/microsoft/fluentui/pull/36278 + * * @public */ export const template: ElementViewTemplate = html` @@ -18,6 +23,7 @@ export const template: ElementViewTemplate = html` @cancel="${x => x.hide()}" ${ref('dialog')} > +
`;