Skip to content

Commit

Permalink
fix(focusTrap): prevent blur if trap container is not in DOM (#1258)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgreif committed May 27, 2021
1 parent 25d88c4 commit 9cb715c
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/tall-pianos-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

prevent focusTrap from causing a `blur` if trap container is not in DOM
29 changes: 29 additions & 0 deletions src/__tests__/behaviors/focusTrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,35 @@ it('Should should release the trap when the signal is aborted', async () => {
expect(document.activeElement).toEqual(durianButton)
})

it('Should should release the trap when the container is removed from the DOM', async () => {
const {container} = render(
<div>
<div id="trapContainer">
<button tabIndex={0}>Apple</button>
</div>
<button id="durian" tabIndex={0}>
Durian
</button>
</div>
)

const trapContainer = container.querySelector<HTMLElement>('#trapContainer')!
const durianButton = container.querySelector<HTMLElement>('#durian')!
const firstButton = trapContainer.querySelector('button')!

focusTrap(trapContainer)

focus(durianButton)
expect(document.activeElement).toEqual(firstButton)

// empty trap and remove it from the DOM
trapContainer.removeChild(firstButton)
trapContainer.parentElement?.removeChild(trapContainer)

focus(durianButton)
expect(document.activeElement).toEqual(durianButton)
})

it('Should handle dynamic content', async () => {
const {container} = render(
<div>
Expand Down
2 changes: 1 addition & 1 deletion src/behaviors/focusTrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function focusTrap(
// is not found, blur the recently-focused element so that focus doesn't leave the
// trap zone.
function ensureTrapZoneHasFocus(focusedElement: EventTarget | null) {
if (focusedElement instanceof HTMLElement) {
if (focusedElement instanceof HTMLElement && document.contains(container)) {
if (container.contains(focusedElement)) {
// If a child of the trap zone was focused, remember it
lastFocusedChild = focusedElement
Expand Down

1 comment on commit 9cb715c

@vercel
Copy link

@vercel vercel bot commented on 9cb715c May 27, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.