Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/spotty-melons-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': patch
---

Add initial loading state to live region announcement in `TreeView`
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ export const AsyncSuccess: StoryFn = args => {
}

AsyncSuccess.args = {
responseTime: 2000,
responseTime: 4000,
}

export const AsyncWithCount: StoryFn = args => {
Expand Down
19 changes: 14 additions & 5 deletions packages/react/src/TreeView/TreeView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<SubTreeState>('loading')
const [state, setState] = React.useState<SubTreeState>('initial')

const setLoadingState = () => {
setState(state === 'initial' ? 'loading' : 'done')
}

return (
<div>
{/* Mimic the completion of async loading by clicking the button */}
<button onClick={() => setState('done')}>Done</button>
<button onClick={setLoadingState}>Load</button>
<TreeView aria-label="Test tree">
<TreeView.Item id="parent" defaultExpanded>
Parent
Expand All @@ -1380,12 +1384,17 @@ describe('Asyncronous loading', () => {
}
const {getByRole} = renderWithTheme(<TestTree />)

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)

Expand Down Expand Up @@ -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')

Expand Down
7 changes: 6 additions & 1 deletion packages/react/src/TreeView/TreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,8 @@ const SubTree: React.FC<TreeViewSubTreeProps> = ({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
Expand Down Expand Up @@ -646,6 +646,11 @@ const SubTree: React.FC<TreeViewSubTreeProps> = ({count, state, children}) => {

setLoadingFocused(false)
}
} else if (state === 'loading') {
if (!parentElement) return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could bubble up as well and return early on 619, since other if statement checks and returns for same condition on 6221

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! So adding if (!parentElement) return at the top rather than in both conditionals. Thank you for the suggestion!


const parentName = getAccessibleName(parentElement)
announceUpdate(`${parentName} content loading`)
}
}, [loadingFocused, previousState, state, itemId, announceUpdate, ref, safeSetTimeout])

Expand Down