From 76ed0074317807a2506f9b3fc861a7597d4787ff Mon Sep 17 00:00:00 2001
From: Clint Goodman
Date: Tue, 17 Nov 2020 10:19:17 -0700
Subject: [PATCH] Add ability to pass containerElements to focus-trap (#179)
Co-authored-by: Clint Goodman
---
.changeset/young-crews-report.md | 5 ++
README.md | 6 ++
cypress/integration/focus-trap-demo.spec.js | 60 ++++++++++++++
demo/index.html | 6 ++
demo/js/demo-containerelements.js | 82 +++++++++++++++++++
demo/js/index.js | 1 +
index.d.ts | 1 +
package.json | 2 +-
src/focus-trap-react.js | 88 +++++++++++++--------
test/activation.test.js | 42 +++++++++-
yarn.lock | 8 +-
11 files changed, 261 insertions(+), 40 deletions(-)
create mode 100644 .changeset/young-crews-report.md
create mode 100644 demo/js/demo-containerelements.js
diff --git a/.changeset/young-crews-report.md b/.changeset/young-crews-report.md
new file mode 100644
index 00000000..3786326a
--- /dev/null
+++ b/.changeset/young-crews-report.md
@@ -0,0 +1,5 @@
+---
+'focus-trap-react': minor
+---
+
+Add ability to pass containerElements to focus-trap #179. This PR is made possible because of https://github.com/focus-trap/focus-trap/pull/217 and the released version 6.2.0 of focus-trap.
diff --git a/README.md b/README.md
index 29115b44..fbe02ef4 100644
--- a/README.md
+++ b/README.md
@@ -161,6 +161,12 @@ Type: `Boolean`, optional
If you would like to pause or unpause the focus trap (see [`focus-trap`'s documentation](https://github.com/focus-trap/focus-trap#focustrappause)), toggle this prop.
+#### containerElements
+
+Type: `Array of HTMLElement`, optional
+
+If passed in, these elements will be used as the boundaries for the focus-trap, instead of the child. These get passed as arguments to focus-trap's updateContainerElements method.
+
## Contributing
See [CONTRIBUTING](CONTRIBUTING.md).
diff --git a/cypress/integration/focus-trap-demo.spec.js b/cypress/integration/focus-trap-demo.spec.js
index 7eeedfd0..1ae93e3c 100644
--- a/cypress/integration/focus-trap-demo.spec.js
+++ b/cypress/integration/focus-trap-demo.spec.js
@@ -241,4 +241,64 @@ describe(' component', () => {
verifyCrucialFocusTrapOnClicking('@trapChild');
});
});
+
+ describe('demo: containerElements prop', () => {
+ it('containerElements can be passed in and used as multiple boundaries to keep the focus within', () => {
+ cy.get('#demo-containerelements').as('testRoot');
+
+ // activate trap
+ cy.get('@testRoot')
+ .findByRole('button', { name: 'activate trap' })
+ .as('lastlyFocusedElementBeforeTrapIsActivated')
+ .click();
+
+ // 1st element should be focused
+ cy.get('@testRoot')
+ .findByRole('link', { name: 'with' })
+ .as('firstElementInTrap')
+ .should('be.focused');
+
+ // trap is active(keep focus in trap by tabbing through the focus trap's tabbable elements)
+ cy.get('@firstElementInTrap')
+ .tab()
+ .should('have.text', 'some')
+ .should('be.focused')
+ .tab()
+ .should('have.text', 'focusable')
+ .should('be.focused')
+ .tab()
+ .should('have.text', 'See')
+ .should('be.focused')
+ .tab()
+ .should('have.text', 'how')
+ .should('be.focused')
+ .tab()
+ .should('have.text', 'works')
+ .should('be.focused')
+ .tab()
+ .should('have.text', 'with')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'works')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'how')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'See')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'focusable')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'some')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'with')
+ .should('be.focused')
+ .tab({ shift: true })
+ .should('have.text', 'works')
+ .should('be.focused');
+ });
+ });
});
diff --git a/demo/index.html b/demo/index.html
index 14da7cb2..8ddaa3e4 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -57,6 +57,12 @@
demo autofocus
+
demo containerElements
+
+ You may pass in an array prop `containerElements` that contains nodes to trap focus within, which if passed will be used instead of the direct child.
+