Skip to content

Commit bc03e45

Browse files
authored
Merge branch 'master' into users/machi/dropdown-typeahead
2 parents 77b220c + cedbb69 commit bc03e45

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "remove tooltip id from target’s aria-describedby attribute when the tooltip is removed from DOM",
4+
"packageName": "@fluentui/web-components",
5+
"email": "machi@microsoft.com",
6+
"dependentChangeType": "patch"
7+
}

packages/web-components/src/tooltip/tooltip.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,45 @@ test.describe('Tooltip', () => {
7171
await expect(button).toHaveAttribute('aria-describedby', id);
7272
});
7373

74+
test('should remove the tooltip id from `aria-describedby` attribute when tooltip is removed', async ({
75+
fastPage,
76+
}) => {
77+
const { element, page } = fastPage;
78+
const button = page.locator('button');
79+
80+
await fastPage.setTemplate(/* html */ `
81+
<div style="position: absolute; inset: 200px">
82+
<button id="target">Target</button>
83+
<${tagName} anchor="target">This is a tooltip</${tagName}>
84+
<${tagName} anchor="target">This is another tooltip</${tagName}>
85+
</div>
86+
`);
87+
88+
const id1 = await element.nth(0).evaluate((node: Tooltip) => node.id);
89+
const id2 = await element.nth(1).evaluate((node: Tooltip) => node.id);
90+
91+
await expect(button).toHaveAttribute('aria-describedby', [id1, id2].join(' '));
92+
93+
await element.nth(0).evaluate(node => {
94+
node.remove();
95+
});
96+
97+
await expect(button).toHaveAttribute('aria-describedby', id2);
98+
99+
await button.evaluate(
100+
(node, [tagName, id]) => {
101+
const tooltip = document.createElement(tagName);
102+
tooltip.id = id;
103+
tooltip.setAttribute('anchor', 'target');
104+
tooltip.textContent = 'New tooltip';
105+
node.after(tooltip);
106+
},
107+
[tagName, id1],
108+
);
109+
110+
await expect(button).toHaveAttribute('aria-describedby', [id2, id1].join(' '));
111+
});
112+
74113
test('should not be visible by default', async ({ fastPage }) => {
75114
const { element } = fastPage;
76115

packages/web-components/src/tooltip/tooltip.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,25 @@ export class Tooltip extends FASTElement {
115115
}
116116

117117
public disconnectedCallback(): void {
118-
super.disconnectedCallback();
119118
this.anchorElement?.removeEventListener('focus', this.focusAnchorHandler);
120119
this.anchorElement?.removeEventListener('blur', this.blurAnchorHandler);
121120
this.anchorElement?.removeEventListener('mouseenter', this.mouseenterAnchorHandler);
122121
this.anchorElement?.removeEventListener('mouseleave', this.mouseleaveAnchorHandler);
122+
123+
if (this.anchorElement) {
124+
const describedBy = this.anchorElement.getAttribute('aria-describedby') ?? '';
125+
const ids = describedBy
126+
.trim()
127+
.split(/\s+/)
128+
.filter(id => id !== this.id);
129+
if (ids.length) {
130+
this.anchorElement.setAttribute('aria-describedby', ids.join(' '));
131+
} else {
132+
this.anchorElement.removeAttribute('aria-describedby');
133+
}
134+
}
135+
136+
super.disconnectedCallback();
123137
}
124138

125139
/**

0 commit comments

Comments
 (0)