diff --git a/.changeset/afraid-pianos-invent.md b/.changeset/afraid-pianos-invent.md
new file mode 100644
index 00000000000..2cf429047ec
--- /dev/null
+++ b/.changeset/afraid-pianos-invent.md
@@ -0,0 +1,5 @@
+---
+"@primer/react": patch
+---
+
+bug: ensure Announce components work without pre-existing text node
diff --git a/packages/react/src/live-region/Announce.tsx b/packages/react/src/live-region/Announce.tsx
index 307a79c47b2..a9e207c83d1 100644
--- a/packages/react/src/live-region/Announce.tsx
+++ b/packages/react/src/live-region/Announce.tsx
@@ -108,6 +108,7 @@ export function Announce({
observer.observe(container, {
subtree: true,
characterData: true,
+ childList: true,
})
return () => {
diff --git a/packages/react/src/live-region/__tests__/AriaAlert.test.tsx b/packages/react/src/live-region/__tests__/AriaAlert.test.tsx
index 91c4d83731e..052eb16552a 100644
--- a/packages/react/src/live-region/__tests__/AriaAlert.test.tsx
+++ b/packages/react/src/live-region/__tests__/AriaAlert.test.tsx
@@ -1,6 +1,7 @@
import {render, screen} from '@testing-library/react'
import React from 'react'
import {AriaAlert} from '../AriaAlert'
+import {userEvent} from '@testing-library/user-event'
import {getLiveRegion} from '../../utils/testing'
describe('AriaAlert', () => {
@@ -46,4 +47,32 @@ describe('AriaAlert', () => {
)
expect(screen.getByTestId('container').tagName).toBe('SPAN')
})
+
+ it('should update live-region element when AriaAlert goes from empty to populated', async () => {
+ function TestComponent() {
+ const [show, setShow] = React.useState(false)
+ return (
+ <>
+ {show ? 'Failed to export data!' : null}
+
+ >
+ )
+ }
+ const user = userEvent.setup()
+
+ render()
+
+ const liveRegion = getLiveRegion()
+ expect(liveRegion.getMessage('assertive')).toBe('')
+
+ await user.click(screen.getByText('Export data'))
+ expect(liveRegion.getMessage('assertive')).toBe('Failed to export data!')
+ })
})
diff --git a/packages/react/src/live-region/__tests__/AriaStatus.test.tsx b/packages/react/src/live-region/__tests__/AriaStatus.test.tsx
index 16465c03a5c..294abf70ee7 100644
--- a/packages/react/src/live-region/__tests__/AriaStatus.test.tsx
+++ b/packages/react/src/live-region/__tests__/AriaStatus.test.tsx
@@ -83,4 +83,32 @@ describe('AriaStatus', () => {
)
expect(screen.getByTestId('container').tagName).toBe('SPAN')
})
+
+ it('should update live-region element when AriaStatus goes from empty to populated', async () => {
+ function TestComponent() {
+ const [show, setShow] = React.useState(false)
+ return (
+ <>
+ {show ? 'Export completed' : null}
+
+ >
+ )
+ }
+ const user = userEvent.setup()
+
+ render()
+
+ const liveRegion = getLiveRegion()
+ expect(liveRegion.getMessage('polite')).toBe('')
+
+ await user.click(screen.getByText('Export data'))
+ expect(liveRegion.getMessage('polite')).toBe('Export completed')
+ })
})