diff --git a/src/__internal__/focus-trap/focus-trap.component.js b/src/__internal__/focus-trap/focus-trap.component.js
index 7dadb01b99..023439f350 100644
--- a/src/__internal__/focus-trap/focus-trap.component.js
+++ b/src/__internal__/focus-trap/focus-trap.component.js
@@ -1,4 +1,4 @@
-import React, {
+import {
useCallback,
useEffect,
useLayoutEffect,
@@ -19,8 +19,8 @@ const FocusTrap = ({
autoFocus = true,
focusFirstElement,
bespokeTrap,
+ wrapperRef,
}) => {
- const ref = useRef();
const firstOpen = useRef(true);
const [focusableElements, setFocusableElements] = useState();
const [firstElement, setFirstElement] = useState();
@@ -38,16 +38,20 @@ const FocusTrap = ({
);
useLayoutEffect(() => {
- const elements = Array.from(
- ref.current.querySelectorAll(defaultFocusableSelectors)
- ).filter((el) => Number(el.tabIndex) !== -1);
-
- if (hasNewInputs(elements)) {
- setFocusableElements(Array.from(elements));
- setFirstElement(elements[0]);
- setLastElement(elements[elements.length - 1]);
+ if (wrapperRef) {
+ const ref = wrapperRef.current || wrapperRef;
+
+ const elements = Array.from(
+ ref.querySelectorAll(defaultFocusableSelectors)
+ ).filter((el) => Number(el.tabIndex) !== -1);
+
+ if (hasNewInputs(elements)) {
+ setFocusableElements(Array.from(elements));
+ setFirstElement(elements[0]);
+ setLastElement(elements[elements.length - 1]);
+ }
}
- }, [children, hasNewInputs]);
+ }, [children, hasNewInputs, wrapperRef]);
useEffect(() => {
if (autoFocus && firstOpen.current && (focusFirstElement || firstElement)) {
@@ -101,7 +105,7 @@ const FocusTrap = ({
};
}, [firstElement, lastElement, focusableElements, bespokeTrap]);
- return
{children}
;
+ return children;
};
FocusTrap.propTypes = {
@@ -115,6 +119,8 @@ FocusTrap.propTypes = {
]),
/** a custom callback that will override the default focus trap behaviour */
bespokeTrap: PropTypes.func,
+ /** a ref to the container wrapping the focusable elements */
+ wrapperRef: PropTypes.shape({ current: PropTypes.any }),
};
export default FocusTrap;
diff --git a/src/__internal__/focus-trap/focus-trap.spec.js b/src/__internal__/focus-trap/focus-trap.spec.js
index c1ef0c0870..d0fcb9b5a1 100644
--- a/src/__internal__/focus-trap/focus-trap.spec.js
+++ b/src/__internal__/focus-trap/focus-trap.spec.js
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useRef } from "react";
import { mount } from "enzyme";
import FocusTrap from "./focus-trap.component";
@@ -9,6 +9,19 @@ import {
jest.useFakeTimers();
+// eslint-disable-next-line
+const MockComponent = ({ children, ...rest }) => {
+ const ref = useRef();
+
+ return (
+
+
+ {children}
+
+
+ );
+};
+
describe("FocusTrap", () => {
const element = document.createElement("div");
const htmlElement = document.body.appendChild(element);
@@ -25,12 +38,10 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
-
-
-
- ,
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -56,12 +67,10 @@ describe("FocusTrap", () => {
document.querySelectorAll("button")[0].focus()
);
wrapper = mount(
-
-
-
-
-
- ,
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -116,12 +125,10 @@ describe("FocusTrap", () => {
beforeEach(() => {
bespokeFn = jest.fn();
mount(
-
-
-
-
-
- ,
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -151,12 +158,10 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
-
-
-
- ,
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -221,11 +226,9 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
- ,
+
+ Test content
+ ,
{ attachTo: htmlElement }
);
});
@@ -248,18 +251,16 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
-
-
-
-
-
- ,
+
+
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -283,31 +284,25 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
- jest.fn()}
- value="1"
- legendWidth={40}
- >
-
-
-
-
-
-
- ,
+
+ jest.fn()}
+ value="1"
+ legendWidth={40}
+ >
+
+
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
@@ -364,31 +359,25 @@ describe("FocusTrap", () => {
beforeEach(() => {
wrapper = mount(
-
-
-
- jest.fn()}
- value="1"
- legendWidth={40}
- >
-
-
-
-
-
- ,
+
+
+ jest.fn()}
+ value="1"
+ legendWidth={40}
+ >
+
+
+
+
+ ,
{ attachTo: htmlElement }
);
});
diff --git a/src/components/dialog-full-screen/dialog-full-screen.component.js b/src/components/dialog-full-screen/dialog-full-screen.component.js
index f8931e2375..2a8a5def74 100644
--- a/src/components/dialog-full-screen/dialog-full-screen.component.js
+++ b/src/components/dialog-full-screen/dialog-full-screen.component.js
@@ -102,7 +102,7 @@ class DialogFullScreen extends Modal {
*/
get modalHTML() {
return (
-
+
{
this._dialog = d;
diff --git a/src/components/dialog/dialog.component.js b/src/components/dialog/dialog.component.js
index 8505d21d05..84ed0472e3 100644
--- a/src/components/dialog/dialog.component.js
+++ b/src/components/dialog/dialog.component.js
@@ -266,6 +266,7 @@ class Dialog extends Modal {
autoFocus={!this.props.disableAutoFocus}
focusFirstElement={this.props.focusFirstElement}
bespokeTrap={this.props.bespokeFocusTrap}
+ wrapperRef={this._dialog}
>
{this.renderDialog(dialogProps)}
diff --git a/src/components/sidebar/sidebar.component.js b/src/components/sidebar/sidebar.component.js
index ebb52a0dcb..753d82e9a6 100644
--- a/src/components/sidebar/sidebar.component.js
+++ b/src/components/sidebar/sidebar.component.js
@@ -68,7 +68,9 @@ class Sidebar extends Modal {
if (this.props.enableBackgroundUI) {
return this.renderSidebar();
}
- return {this.renderSidebar()};
+ return (
+ {this.renderSidebar()}
+ );
}
}