Skip to content

Commit

Permalink
fix: use text content of whole live region when updating announcements (
Browse files Browse the repository at this point in the history
#11)

- Previously text content was read from the changed node
  • Loading branch information
AriPerkkio committed Oct 17, 2021
1 parent f21a6fa commit 0b11bf5
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .storybook/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function formatSourceCode(str: string) {
.replace(/(>\n)(<\w)/g, '$1\n$2')

// Replace self-ending tags with starting and ending tags
.replace(/<(\w+)((\w|\s|\n|=|"|-)+)\/>/g, '<$1 $2>\n</$1>')
.replace(/( *)<(\w+)((\s|\w|=|"|-)*)\s*\/>/g, '$1<$2 $3>\n$1</$2>')

// Align attributes to same level as tag when there is only a single attribute
.replace(/<(\w+) *\n +((\w|=|"|-)+)\n *>/g, '<$1 $2>')
Expand Down
23 changes: 23 additions & 0 deletions .storybook/stories/AriaLiveAssertive.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,26 @@ export function ContentIsPartiallyHidden() {
`
);
}

addStoryName(PartOfContentChanges, 'PASS');
export function PartOfContentChanges() {
return createMountToggle(
`
<div aria-live="assertive">
<span>
Hello
</span>
</div>
`,
`
<div aria-live="assertive">
<span>
Hello
</span>
<span>
world
</span>
</div>
`
);
}
3 changes: 1 addition & 2 deletions .storybook/virtual-dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ function trimWhitespace(text: string) {
return text
.replace(/\s+/g, ' ')
.replace(/\n+/, '\n')
.replace(/> +/g, '>')
.replace(/ +</g, '<')
.replace(/> *(\w*) *</g, '>$1<')
.trim();
}
61 changes: 32 additions & 29 deletions src/capture-announcements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,18 @@ export default function CaptureAnnouncements(options: Options): Restore {
if (!element) return;
if (isHidden(element)) return;

const closestLiveRegion = getClosestLiveRegion(element);
const liveRegion = getClosestLiveRegion(element);

if (closestLiveRegion) {
const politenessSetting = resolvePolitenessSetting(
closestLiveRegion
);
if (liveRegion) {
const politenessSetting = resolvePolitenessSetting(liveRegion);

if (politenessSetting !== 'off' && isInDOM(closestLiveRegion)) {
// TODO: Use text content of live container, not the updated node's.
const previousText = liveRegions.get(element);
const newText = getTextContent(element) || '';
if (politenessSetting !== 'off' && isInDOM(liveRegion)) {
const previousText = liveRegions.get(liveRegion);
const newText = getTextContent(liveRegion) || '';

if (previousText !== newText) {
onCapture(newText, politenessSetting);
liveRegions.set(element, newText);
liveRegions.set(liveRegion, newText);
}
}
}
Expand Down Expand Up @@ -215,6 +212,31 @@ export default function CaptureAnnouncements(options: Options): Restore {
}
}

function onRemoveChild(
this: Element,
...args: Parameters<Element['removeChild']>
) {
const [node] = args;

if (node == null || !isElement(node)) {
return updateAnnouncements(this);
}

const elementAndItsLiveRegionChildren = [
node,
...node.querySelectorAll(LIVE_REGION_QUERY),
];

// Check whether removed element or any of its children were tracked
for (const element of elementAndItsLiveRegionChildren) {
if (liveRegions.has(element)) {
liveRegions.delete(element);
}
}

updateAnnouncements(this);
}

// prettier-ignore
const cleanups: Restore[] = [
interceptMethod(Element.prototype, 'setAttribute', onSetAttribute),
Expand Down Expand Up @@ -261,25 +283,6 @@ function onRemoveAttributeBefore(
}
}

function onRemoveChild(
this: Element,
...args: Parameters<Element['removeChild']>
) {
if (args[0] == null || !isElement(args[0])) return;

const elementAndItsLiveRegionChildren = [
args[0],
...args[0].querySelectorAll(LIVE_REGION_QUERY),
];

// Check whether removed element or any of its children were tracked
for (const element of elementAndItsLiveRegionChildren) {
if (liveRegions.has(element)) {
liveRegions.delete(element);
}
}
}

/** Not part of public API, do not use */
export const __PrivateUnstableAPI = {
liveRegions,
Expand Down
21 changes: 21 additions & 0 deletions test/capture-announcements.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,27 @@ describe.each(POLITE_CASES)('$testName', ({ name, value, tag }) => {

expect(onCapture).not.toHaveBeenCalled();
});

test('should announce whole content when a single child changes', () => {
appendToRoot(element);

const first = document.createElement('div');
first.textContent = 'Hello';
element.appendChild(first);

expect(onCapture).toHaveBeenCalledWith('Hello', 'polite');
onCapture.mockClear();

const second = document.createElement('div');
element.appendChild(second);

second.textContent = 'World';
expect(onCapture).toHaveBeenCalledWith('Hello World', 'polite');
onCapture.mockClear();

element.removeChild(second);
expect(onCapture).toHaveBeenCalledWith('Hello', 'polite');
});
});

describe.each(ASSERTIVE_CASES)('$testName', ({ name, value }) => {
Expand Down

0 comments on commit 0b11bf5

Please sign in to comment.