diff --git a/docs/index.md b/docs/index.md
index d3ddf032..4c621eba 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -153,7 +153,16 @@ import ReactModal from 'react-modal';
contentRef={
setContentRef
- /* Content ref callback. */}>
+ /* Content ref callback. */}
+
+ overlayElement={
+ (props, contentElement) =>
{contentElement}
+ /* Custom Overlay element. */}
+
+ contentElement={
+ (props, children) => {children}
+ /* Custom Content element. */}
+ >
Modal Content
```
diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js
index 4bd1fe2d..d13f1fe3 100644
--- a/specs/Modal.spec.js
+++ b/specs/Modal.spec.js
@@ -237,8 +237,8 @@ export default () => {
it("supports id prop", () => {
const modal = renderModal({ isOpen: true, id: "id" });
mcontent(modal)
- .id.includes("id")
- .should.be.ok();
+ .id
+ .should.be.eql("id");
});
it("supports portalClassName", () => {
@@ -256,6 +256,33 @@ export default () => {
.should.be.ok();
});
+ it("supports custom overlayElement", () => {
+ const overlayElement = (props, contentElement) => (
+
+ {contentElement}
+
+ );
+
+ const modal = renderModal({ isOpen: true, overlayElement });
+ const modalOverlay = moverlay(modal);
+
+ modalOverlay.id.should.eql("custom");
+ });
+
+ it("supports custom contentElement", () => {
+ const contentElement = (props, children) => (
+
+ {children}
+
+ );
+
+ const modal = renderModal({ isOpen: true, contentElement }, "hello");
+ const modalContent = mcontent(modal);
+
+ modalContent.id.should.eql("custom");
+ modalContent.textContent.should.be.eql("hello");
+ });
+
it("supports overlayClassName", () => {
const modal = renderModal({
isOpen: true,
diff --git a/src/components/Modal.js b/src/components/Modal.js
index 79bc7734..9b4fa519 100644
--- a/src/components/Modal.js
+++ b/src/components/Modal.js
@@ -68,7 +68,10 @@ class Modal extends Component {
contentLabel: PropTypes.string,
shouldCloseOnEsc: PropTypes.bool,
overlayRef: PropTypes.func,
- contentRef: PropTypes.func
+ contentRef: PropTypes.func,
+ id: PropTypes.string,
+ overlayElement: PropTypes.func,
+ contentElement: PropTypes.func
};
/* eslint-enable react/no-unused-prop-types */
@@ -84,7 +87,9 @@ class Modal extends Component {
shouldCloseOnOverlayClick: true,
shouldReturnFocusAfterClose: true,
preventScroll: false,
- parentSelector: () => document.body
+ parentSelector: () => document.body,
+ overlayElement: (props, contentEl) => {contentEl}
,
+ contentElement: (props, children) => {children}
};
static defaultStyles = {
diff --git a/src/components/ModalPortal.js b/src/components/ModalPortal.js
index 17768eae..c84a52f0 100644
--- a/src/components/ModalPortal.js
+++ b/src/components/ModalPortal.js
@@ -61,6 +61,8 @@ export default class ModalPortal extends Component {
overlayRef: PropTypes.func,
contentRef: PropTypes.func,
id: PropTypes.string,
+ overlayElement: PropTypes.func,
+ contentElement: PropTypes.func,
testId: PropTypes.string
};
@@ -343,37 +345,40 @@ export default class ModalPortal extends Component {
}, {});
render() {
- const { id, className, overlayClassName, defaultStyles } = this.props;
+ const { id, className, overlayClassName, defaultStyles, children } = this.props;
const contentStyles = className ? {} : defaultStyles.content;
const overlayStyles = overlayClassName ? {} : defaultStyles.overlay;
- return this.shouldBeClosed() ? null : (
-
-
- {this.props.children}
-
-
- );
+ if (this.shouldBeClosed()) {
+ return null;
+ }
+
+ const overlayProps = {
+ ref: this.setOverlayRef,
+ className: this.buildClassName("overlay", overlayClassName),
+ style: { ...overlayStyles, ...this.props.style.overlay },
+ onClick: this.handleOverlayOnClick,
+ onMouseDown: this.handleOverlayOnMouseDown
+ };
+
+ const contentProps = {
+ id,
+ ref: this.setContentRef,
+ style: { ...contentStyles, ...this.props.style.content },
+ className: this.buildClassName("content", className),
+ tabIndex: "-1",
+ onKeyDown: this.handleKeyDown,
+ onMouseDown: this.handleContentOnMouseDown,
+ onMouseUp: this.handleContentOnMouseUp,
+ onClick: this.handleContentOnClick,
+ role: this.props.role,
+ "aria-label": this.props.contentLabel,
+ ...this.attributesFromObject("aria", this.props.aria || {}),
+ ...this.attributesFromObject("data", this.props.data || {}),
+ "data-testid": this.props.testId
+ };
+
+ const contentElement = this.props.contentElement(contentProps, children);
+ return this.props.overlayElement(overlayProps, contentElement);
}
}