Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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/clever-cats-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/view-components": patch
---

Make Retry button focusable in loading_failure_story
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,60 @@
const includeFragment = subject.querySelector('tree-view-include-fragment')
if (!includeFragment) return

includeFragment.addEventListener('loadend', (event) => {
function retryButton() {
return subject.querySelector("[data-target='tree-view-sub-tree-node.retryButton']")
}

function focusTreeItem() {
const treeItem = subject.querySelector("[role='treeitem']")
if (treeItem) treeItem.focus()
}

function makeRetryTabbable() {
const retry = retryButton()
if (!retry) return
// Remove tabindex="-1" so the button can be reached by keyboard.
retry.removeAttribute('tabindex')
}

function addRetryFocusHandler() {
const retry = retryButton()
if (!retry) return

if (retry.dataset.focusHandlerAttached === "true") return
retry.dataset.focusHandlerAttached = "true"

retry.addEventListener('click', () => {
focusTreeItem()
})
}

// When the failure UI loads, ensure Retry is tabbable
includeFragment.addEventListener('loadend', (_event) => {
makeRetryTabbable()
addRetryFocusHandler()
subject.setAttribute('data-ready', 'true')
})

// If include-fragment swaps in new markup on re-render, re-apply tabindex removal.
includeFragment.addEventListener('include-fragment-replaced', () => {
makeRetryTabbable()
addRetryFocusHandler()
})

// If Retry exists and the user presses Tab while focused inside this TreeView,
// redirect focus to Retry so it is reachable without requiring a mouse click.
subject.addEventListener('keydown', (event) => {
if (event.key !== 'Tab' || event.shiftKey) return
const active = document.activeElement
if (!(active instanceof HTMLElement)) return
if (!subject.contains(active)) return
if (active.getAttribute('role') !== 'treeitem') return
const retry = retryButton()
if (!retry) return
makeRetryTabbable()
event.preventDefault()
retry.focus()
})
})
</script>
Loading