diff --git a/.changeset/fresh-frogs-smoke.md b/.changeset/fresh-frogs-smoke.md
new file mode 100644
index 00000000000..2a805242144
--- /dev/null
+++ b/.changeset/fresh-frogs-smoke.md
@@ -0,0 +1,5 @@
+---
+"@primer/react": patch
+---
+
+TreeView: Add `state` prop to `TreeView.SubTree` component
diff --git a/.changeset/light-coats-mate.md b/.changeset/light-coats-mate.md
new file mode 100644
index 00000000000..5b7b684b340
--- /dev/null
+++ b/.changeset/light-coats-mate.md
@@ -0,0 +1,5 @@
+---
+"@primer/react": patch
+---
+
+TreeView: Improve accessibility of async items
diff --git a/docs/content/TreeView.mdx b/docs/content/TreeView.mdx
index 0c0250368c5..823847beffc 100644
--- a/docs/content/TreeView.mdx
+++ b/docs/content/TreeView.mdx
@@ -278,6 +278,37 @@ See [Storybook](https://primer.style/react/storybook?path=/story/components-tree
+
+ Specify a state if items in the subtree are loaded asynchronously.
+
+ An asynchronous subtree can be in one of the following states:
+
+ -
+ initial: Items are neither loaded nor loading.
+
+ -
+ loading: Currently loading items. The subtree will render a loading indicator
+ when in this state (after a 300ms delay).
+
+ -
+ done: Done loading items. Screen readers will announce when a subtree enters this
+ state.
+
+ -
+ error: An error occured while loading items.
+
+
+
+ >
+ }
+ />
{/* */}
diff --git a/src/TreeView/TreeView.stories.tsx b/src/TreeView/TreeView.stories.tsx
index e6b8296c9d2..f7f69ade55f 100644
--- a/src/TreeView/TreeView.stories.tsx
+++ b/src/TreeView/TreeView.stories.tsx
@@ -7,7 +7,7 @@ import Box from '../Box'
import {Button} from '../Button'
import {ConfirmationDialog} from '../Dialog/ConfirmationDialog'
import StyledOcticon from '../StyledOcticon'
-import {TreeView} from './TreeView'
+import {SubTreeState, TreeView} from './TreeView'
const meta: Meta = {
title: 'Components/TreeView',
@@ -409,6 +409,14 @@ export const AsyncSuccess: Story = args => {
const [isLoading, setIsLoading] = React.useState(false)
const [asyncItems, setAsyncItems] = React.useState([])
+ let state: SubTreeState = 'initial'
+
+ if (isLoading) {
+ state = 'loading'
+ } else if (asyncItems.length > 0) {
+ state = 'done'
+ }
+
return (