From 5dfee233df2c5ee3782b0cf68b3527c4346068d6 Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Mon, 16 Sep 2024 12:57:37 -0400 Subject: [PATCH 1/5] Add indication for "Loading" for screen readers --- packages/react/src/TreeView/TreeView.features.stories.tsx | 2 +- packages/react/src/TreeView/TreeView.tsx | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.features.stories.tsx b/packages/react/src/TreeView/TreeView.features.stories.tsx index 14a88a43a93..b4d9a8181b4 100644 --- a/packages/react/src/TreeView/TreeView.features.stories.tsx +++ b/packages/react/src/TreeView/TreeView.features.stories.tsx @@ -407,7 +407,7 @@ export const AsyncSuccess: StoryFn = args => { } AsyncSuccess.args = { - responseTime: 2000, + responseTime: 4000, } export const AsyncWithCount: StoryFn = args => { diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index 401f81ac03b..fde9e95fb5f 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -616,8 +616,8 @@ const SubTree: React.FC = ({count, state, children}) => { // Handle transition from loading to done state React.useEffect(() => { + const parentElement = document.getElementById(itemId) if (previousState === 'loading' && state === 'done') { - const parentElement = document.getElementById(itemId) if (!parentElement) return // Announce update to screen readers @@ -646,6 +646,11 @@ const SubTree: React.FC = ({count, state, children}) => { setLoadingFocused(false) } + } else if (state === 'loading') { + if (!parentElement) return + + const parentName = getAccessibleName(parentElement) + announceUpdate(`${parentName} content loading`) } }, [loadingFocused, previousState, state, itemId, announceUpdate, ref, safeSetTimeout]) From 75af18001c58716495b54a3b40df4bf6b0932a1e Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Mon, 16 Sep 2024 18:17:57 -0400 Subject: [PATCH 2/5] Update test --- packages/react/src/TreeView/TreeView.test.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.test.tsx b/packages/react/src/TreeView/TreeView.test.tsx index 3dc535270fa..6cb02611ca7 100644 --- a/packages/react/src/TreeView/TreeView.test.tsx +++ b/packages/react/src/TreeView/TreeView.test.tsx @@ -1354,12 +1354,16 @@ describe('State', () => { describe('Asyncronous loading', () => { it('updates aria live region when loading is done', () => { function TestTree() { - const [state, setState] = React.useState('loading') + const [state, setState] = React.useState('initial') + + const setLoadingState = () => { + setState(state === 'initial' ? 'loading' : 'done') + } return (
{/* Mimic the completion of async loading by clicking the button */} - + Parent @@ -1380,12 +1384,17 @@ describe('Asyncronous loading', () => { } const {getByRole} = renderWithTheme() - const doneButton = getByRole('button', {name: 'Done'}) + const doneButton = getByRole('button', {name: 'Load'}) const liveRegion = getByRole('status') // Live region should be empty expect(liveRegion).toHaveTextContent('') + // Click load button to mimic async loading + fireEvent.click(doneButton) + + expect(liveRegion).toHaveTextContent('Parent content loading') + // Click done button to mimic the completion of async loading fireEvent.click(doneButton) @@ -1563,9 +1572,9 @@ describe('Asyncronous loading', () => { advanceTimers: jest.advanceTimersByTime, }) - const treeitem = getByLabelText(/Item 1/) + const treeitem = getByLabelText('Item 1') expect(treeitem).toHaveAttribute('aria-expanded', 'false') - await user.click(getByText(/Item 1/)) + await user.click(getByText('Item 1')) expect(treeitem).toHaveAttribute('aria-expanded', 'true') From b9012a9690332986e3c2683e69d5f7b59d243bf0 Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Mon, 16 Sep 2024 18:21:58 -0400 Subject: [PATCH 3/5] Add changeset --- .changeset/spotty-melons-sit.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spotty-melons-sit.md diff --git a/.changeset/spotty-melons-sit.md b/.changeset/spotty-melons-sit.md new file mode 100644 index 00000000000..8b3043deae2 --- /dev/null +++ b/.changeset/spotty-melons-sit.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Add initial loading state to live region announcement in `TreeView` From 629dc4aa1e20d9778ea27221b303b1613ad5079e Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Fri, 27 Sep 2024 10:18:29 -0400 Subject: [PATCH 4/5] Return early --- packages/react/src/TreeView/TreeView.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index fde9e95fb5f..a6fbac25fcb 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -617,9 +617,8 @@ const SubTree: React.FC = ({count, state, children}) => { // Handle transition from loading to done state React.useEffect(() => { const parentElement = document.getElementById(itemId) + if (!parentElement) return if (previousState === 'loading' && state === 'done') { - if (!parentElement) return - // Announce update to screen readers const parentName = getAccessibleName(parentElement) @@ -647,8 +646,6 @@ const SubTree: React.FC = ({count, state, children}) => { setLoadingFocused(false) } } else if (state === 'loading') { - if (!parentElement) return - const parentName = getAccessibleName(parentElement) announceUpdate(`${parentName} content loading`) } From 3861150b39ce1e245cf844566168b7152f7f7bd9 Mon Sep 17 00:00:00 2001 From: Tyler Jones Date: Fri, 27 Sep 2024 10:45:09 -0400 Subject: [PATCH 5/5] Fix test --- packages/react/src/TreeView/TreeView.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/TreeView/TreeView.test.tsx b/packages/react/src/TreeView/TreeView.test.tsx index d45228bfc08..056b6714acb 100644 --- a/packages/react/src/TreeView/TreeView.test.tsx +++ b/packages/react/src/TreeView/TreeView.test.tsx @@ -1364,7 +1364,7 @@ describe('Asyncronous loading', () => {
{/* Mimic the completion of async loading by clicking the button */}