Repository: mapbox/mr-ui
Pull request #134 (2021-06-24 21:21:05)

1.0.0
@elifitch this branch is a fork off of the react-16 branch you were working on a while back. Did we have a backlog of things we wanted to take care of before the 1.0.0 release? Going to create a new 1.0.0 prerelease now to unblock https://github.com/mapbox/studio/pull/14704

cc: @thefifthisa 

samanpwbb: @katydecorah do you think you could give this a review when you get a chance? Studio is reliant on this branch. I don't see a good reason not to go 1.0.0 now. We can always go to 2.0.0 when we need it.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5475e2c..1b579ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,9 @@
 # Changelog
+## 1.0.0
+
+- [feature] Trap events in modals by default
+- [fix] Fix coloring values for popover
+- [fix] rename unsafe lifecycle methods to eliminate warnings under React 16
 
 ## 0.12.0
 
diff --git a/package-lock.json b/package-lock.json
index eea539d..f805974 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "@mapbox/mr-ui",
-  "version": "0.12.0",
+  "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index da6eb34..0ac3993 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "@mapbox/mr-ui",
-  "version": "0.12.0",
+  "version": "1.0.0",
   "description": "UI components for Mapbox projects",
   "main": "index.js",
   "scripts": {
@@ -98,9 +98,9 @@
     "pify": "^3.0.0",
     "prettier": "^2.3.1",
     "prismjs": "^1.15.0",
-    "react": "^16.4.1",
+    "react": "^16.14.0",
     "react-docgen": "^2.21.0",
-    "react-dom": "^16.4.1",
+    "react-dom": "^16.14.0",
     "react-helmet": "^5.2.0",
     "react-test-renderer": "^16.4.1",
     "regenerator-runtime": "^0.13.7"
diff --git a/src/components/control-file/control-file.js b/src/components/control-file/control-file.js
index 0e1713f..ba0ac27 100644
--- a/src/components/control-file/control-file.js
+++ b/src/components/control-file/control-file.js
@@ -86,7 +86,7 @@ export default class ControlFile extends React.Component {
     displayValue: ''
   };
 
-  componentWillReceiveProps(nextProps) {
+  UNSAFE_componentWillReceiveProps(nextProps) {
     const nextDisplayValue = !nextProps.value
       ? ''
       : nextProps.value.map((f) => f.name).join(', ');
diff --git a/src/components/copy-button/copy-button.js b/src/components/copy-button/copy-button.js
index a497f3e..70b3a9d 100644
--- a/src/components/copy-button/copy-button.js
+++ b/src/components/copy-button/copy-button.js
@@ -50,7 +50,7 @@ export default class CopyButton extends React.PureComponent {
     }, FEEDBACK_TIME);
   };
 
-  componentWillReceiveProps(nextProps) {
+  UNSAFE_componentWillReceiveProps(nextProps) {
     const copyAvailable = Clipboard.isSupported();
     if (nextProps.textEl !== this.props.textEl && copyAvailable) {
       this.setClipboard(nextProps.textEl);
diff --git a/src/components/form/form.js b/src/components/form/form.js
index 7a4416b..f8b0e14 100644
--- a/src/components/form/form.js
+++ b/src/components/form/form.js
@@ -88,7 +88,7 @@ export default class Form extends React.Component {
     });
   }
 
-  componentWillReceiveProps(nextProps) {
+  UNSAFE_componentWillReceiveProps(nextProps) {
     const { config } = this.props;
     if (!shallowEqualObjects(nextProps.config, config)) {
       const { controlValues, controlValidationErrors } =
diff --git a/src/components/minimum-duration-loader/minimum-duration-loader.js b/src/components/minimum-duration-loader/minimum-duration-loader.js
index 742cb47..3e99adc 100644
--- a/src/components/minimum-duration-loader/minimum-duration-loader.js
+++ b/src/components/minimum-duration-loader/minimum-duration-loader.js
@@ -41,7 +41,7 @@ export default class MinimumDurationLoader extends React.PureComponent {
     }
   }
 
-  componentWillReceiveProps(nextProps) {
+  UNSAFE_componentWillReceiveProps(nextProps) {
     const currentTime = Date.now();
 
     if (!nextProps.isLoaded && this._delayedMountTimeout !== null) {
diff --git a/src/components/modal/event-trap.js b/src/components/modal/event-trap.js
new file mode 100644
index 0000000..046fa0c
--- /dev/null
+++ b/src/components/modal/event-trap.js
@@ -0,0 +1,50 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const trap = e => e.stopPropagation();
+
+function EventTrap({ children }) {
+  return (
+    <div
+      onClick={trap}
+      onContextMenu={trap}
+      onDoubleClick={trap}
+      onDrag={trap}
+      onDragEnd={trap}
+      onDragEnter={trap}
+      onDragExit={trap}
+      onDragLeave={trap}
+      onDragOver={trap}
+      onDragStart={trap}
+      onDrop={trap}
+      onMouseDown={trap}
+      onMouseEnter={trap}
+      onMouseLeave={trap}
+      onMouseMove={trap}
+      onMouseOver={trap}
+      onMouseOut={trap}
+      onMouseUp={trap}
+      onKeyDown={trap}
+      onKeyPress={trap}
+      onKeyUp={trap}
+      onFocus={trap}
+      onBlur={trap}
+      onChange={trap}
+      onInput={trap}
+      onInvalid={trap}
+      onSubmit={trap}
+      onTouchCancel={trap}
+      onTouchEnd={trap}
+      onTouchMove={trap}
+      onTouchStart={trap}
+    >
+      {children}
+    </div>
+  );
+}
+
+EventTrap.propTypes = {
+  children: PropTypes.node.isRequired
+};
+
+export default EventTrap;
diff --git a/src/components/modal/modal.js b/src/components/modal/modal.js
index 99fb72f..38a41e1 100644
--- a/src/components/modal/modal.js
+++ b/src/components/modal/modal.js
@@ -6,6 +6,7 @@ import Tooltip from '../tooltip';
 import Icon from '../icon';
 import getWindow from '../utils/get-window';
 import ModalActions from './modal-actions';
+import EventTrap from './event-trap';
 
 /**
  * An accessible modal dialog.
@@ -135,6 +136,15 @@ export default class Modal extends React.Component {
       modalProps.focusTrapPaused = true;
     }
 
+    if (!props.allowEventBubbling) {
+      // stopPropagation prevents child modals from closing parent modals when nesting
+      return (
+        <EventTrap>
+          <AriaModal {...modalProps}>{dialogBody}</AriaModal>
+        </EventTrap>
+      );
+    }
+
     return <AriaModal {...modalProps}>{dialogBody}</AriaModal>;
   }
 }
@@ -244,7 +254,13 @@ Modal.propTypes = {
   tertiaryAction: PropTypes.shape({
     text: PropTypes.string.isRequired,
     callback: PropTypes.func.isRequired
-  })
+  }),
+  /**
+   * We stop propagation on clicks by default to enable more intuitive
+   * operation with React Portals. If you need click events to bubble up
+   * to parent components, set this prop to true
+   */
+  allowEventBubbling: PropTypes.bool
 };
 
 Modal.defaultProps = {
diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js
index 11d0959..a5def7b 100644
--- a/src/components/popover/popover.js
+++ b/src/components/popover/popover.js
@@ -33,7 +33,7 @@ export default class Popover extends React.Component {
     this.popoverId = popoverCounter;
   }
 
-  componentWillMount() {
+  UNSAFE_componentWillMount() {
     // For focus management: focus will return to this element
     // when the popover is closed
     this.previouslyFocusedElement = document.activeElement;
@@ -364,13 +364,13 @@ function noop() {}
 function getColors(coloring) {
   if (coloring === 'dark') {
     return {
-      background: '#273d56', // gray-dark
+      background: '#0E2127', // gray-dark
       textClass: 'color-white'
     };
   }
   if (coloring === 'warning') {
     return {
-      background: '#FFF5A0', // yellow-light
+      background: '#FBC997', // orange-light
       textClass: 'color-text'
     };
   }


Test patch:
diff --git a/src/components/modal/__tests__/__snapshots__/modal.test.js.snap b/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
index 9326ec6..5b13846 100644
--- a/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
+++ b/src/components/modal/__tests__/__snapshots__/modal.test.js.snap
@@ -1,317 +1,327 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Modal No fixed width, display only renders 1`] = `
-<Displaced
-  focusDialog={true}
-  getApplicationNode={[Function]}
-  mounted={true}
-  onExit={[MockFunction]}
-  titleText="Auto modal title"
-  underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
-  underlayProps={
-    Object {
-      "data-popover-ignore-clicks": true,
+<EventTrap>
+  <Displaced
+    focusDialog={true}
+    getApplicationNode={[Function]}
+    mounted={true}
+    onExit={[MockFunction]}
+    titleText="Auto modal title"
+    underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
+    underlayProps={
+      Object {
+        "data-popover-ignore-clicks": true,
+      }
     }
-  }
-  underlayStyle={
-    Object {
-      "zIndex": 1,
+    underlayStyle={
+      Object {
+        "zIndex": 1,
+      }
     }
-  }
->
-  <div
-    className="relative wmax-full  bg-white round px36 py36"
   >
-    <div>
-      No fixed width on the modal container. But very tall.
-    </div>
     <div
-      className="absolute top right"
+      className="relative wmax-full  bg-white round px36 py36"
     >
-      <Tooltip
-        alignment="center"
-        block={true}
-        coloring="light"
-        content="Close"
-        disabled={false}
-        maxWidth="medium"
-        padding="small"
-        placement="top"
-        respondsToClick={false}
-        textSize="s"
+      <div>
+        No fixed width on the modal container. But very tall.
+      </div>
+      <div
+        className="absolute top right"
       >
-        <button
-          aria-label="Close"
-          className="btn btn--transparent unround-t unround-br color-gray py12 px12"
-          data-test="modal-close"
-          onClick={[MockFunction]}
-          type="button"
+        <Tooltip
+          alignment="center"
+          block={true}
+          coloring="light"
+          content="Close"
+          disabled={false}
+          maxWidth="medium"
+          padding="small"
+          placement="top"
+          respondsToClick={false}
+          textSize="s"
         >
-          <Icon
-            inline={false}
-            name="close"
-            passthroughProps={Object {}}
-            size={18}
-          />
-        </button>
-      </Tooltip>
+          <button
+            aria-label="Close"
+            className="btn btn--transparent unround-t unround-br color-gray py12 px12"
+            data-test="modal-close"
+            onClick={[MockFunction]}
+            type="button"
+          >
+            <Icon
+              inline={false}
+              name="close"
+              passthroughProps={Object {}}
+              size={18}
+            />
+          </button>
+        </Tooltip>
+      </div>
     </div>
-  </div>
-</Displaced>
+  </Displaced>
+</EventTrap>
 `;
 
 exports[`Modal all options renders 1`] = `
-<Displaced
-  getApplicationNode={[Function]}
-  initialFocus="#foo"
-  mounted={true}
-  onExit={[MockFunction]}
-  titleText="All options"
-  underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
-  underlayProps={
-    Object {
-      "data-popover-ignore-clicks": true,
+<EventTrap>
+  <Displaced
+    getApplicationNode={[Function]}
+    initialFocus="#foo"
+    mounted={true}
+    onExit={[MockFunction]}
+    titleText="All options"
+    underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
+    underlayProps={
+      Object {
+        "data-popover-ignore-clicks": true,
+      }
     }
-  }
-  underlayStyle={
-    Object {
-      "zIndex": 1,
+    underlayStyle={
+      Object {
+        "zIndex": 1,
+      }
     }
-  }
->
-  <div
-    className="relative wmax-full w360 bg-white round px36 py36"
   >
-    <div>
-      <div
-        className="mb12"
-      >
-        I am a message
-      </div>
-      <button
-        aria-label="press me"
-        className="btn"
-        id="foo"
-      >
-        press me
-      </button>
-    </div>
     <div
-      className="absolute top right"
+      className="relative wmax-full w360 bg-white round px36 py36"
     >
-      <Tooltip
-        alignment="center"
-        block={true}
-        coloring="light"
-        content="Close"
-        disabled={false}
-        maxWidth="medium"
-        padding="small"
-        placement="top"
-        respondsToClick={false}
-        textSize="s"
-      >
+      <div>
+        <div
+          className="mb12"
+        >
+          I am a message
+        </div>
         <button
-          aria-label="Close"
-          className="btn btn--transparent unround-t unround-br color-gray py12 px12"
-          data-test="modal-close"
-          onClick={[MockFunction]}
-          type="button"
+          aria-label="press me"
+          className="btn"
+          id="foo"
         >
-          <Icon
-            inline={false}
-            name="close"
-            passthroughProps={Object {}}
-            size={18}
-          />
+          press me
         </button>
-      </Tooltip>
+      </div>
+      <div
+        className="absolute top right"
+      >
+        <Tooltip
+          alignment="center"
+          block={true}
+          coloring="light"
+          content="Close"
+          disabled={false}
+          maxWidth="medium"
+          padding="small"
+          placement="top"
+          respondsToClick={false}
+          textSize="s"
+        >
+          <button
+            aria-label="Close"
+            className="btn btn--transparent unround-t unround-br color-gray py12 px12"
+            data-test="modal-close"
+            onClick={[MockFunction]}
+            type="button"
+          >
+            <Icon
+              inline={false}
+              name="close"
+              passthroughProps={Object {}}
+              size={18}
+            />
+          </button>
+        </Tooltip>
+      </div>
     </div>
-  </div>
-</Displaced>
+  </Displaced>
+</EventTrap>
 `;
 
 exports[`Modal basic default renders 1`] = `
-<Displaced
-  focusDialog={true}
-  getApplicationNode={[Function]}
-  mounted={true}
-  onExit={[MockFunction]}
-  titleText="Large modal title"
-  underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
-  underlayProps={
-    Object {
-      "data-popover-ignore-clicks": true,
+<EventTrap>
+  <Displaced
+    focusDialog={true}
+    getApplicationNode={[Function]}
+    mounted={true}
+    onExit={[MockFunction]}
+    titleText="Large modal title"
+    underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
+    underlayProps={
+      Object {
+        "data-popover-ignore-clicks": true,
+      }
     }
-  }
-  underlayStyle={
-    Object {
-      "zIndex": 1,
+    underlayStyle={
+      Object {
+        "zIndex": 1,
+      }
     }
-  }
->
-  <div
-    className="relative wmax-full w600 bg-white round px36 py36"
   >
-    <div>
-      Large modal body
-    </div>
     <div
-      className="mt24"
+      className="relative wmax-full w600 bg-white round px36 py36"
     >
-      <ModalActions
-        primaryAction={
-          Object {
-            "callback": [MockFunction],
-            "destructive": true,
-            "text": "Okay",
+      <div>
+        Large modal body
+      </div>
+      <div
+        className="mt24"
+      >
+        <ModalActions
+          primaryAction={
+            Object {
+              "callback": [MockFunction],
+              "destructive": true,
+              "text": "Okay",
+            }
           }
-        }
-        secondaryAction={
-          Object {
-            "callback": [MockFunction],
-            "text": "Cancel",
+          secondaryAction={
+            Object {
+              "callback": [MockFunction],
+              "text": "Cancel",
+            }
           }
-        }
-        tertiaryAction={
-          Object {
-            "callback": [MockFunction],
-            "text": "Give up",
+          tertiaryAction={
+            Object {
+              "callback": [MockFunction],
+              "text": "Give up",
+            }
           }
-        }
-      />
-    </div>
-    <div
-      className="absolute top right"
-    >
-      <Tooltip
-        alignment="center"
-        block={true}
-        coloring="light"
-        content="Close"
-        disabled={false}
-        maxWidth="medium"
-        padding="small"
-        placement="top"
-        respondsToClick={false}
-        textSize="s"
+        />
+      </div>
+      <div
+        className="absolute top right"
       >
-        <button
-          aria-label="Close"
-          className="btn btn--transparent unround-t unround-br color-gray py12 px12"
-          data-test="modal-close"
-          onClick={[MockFunction]}
-          type="button"
+        <Tooltip
+          alignment="center"
+          block={true}
+          coloring="light"
+          content="Close"
+          disabled={false}
+          maxWidth="medium"
+          padding="small"
+          placement="top"
+          respondsToClick={false}
+          textSize="s"
         >
-          <Icon
-            inline={false}
-            name="close"
-            passthroughProps={Object {}}
-            size={18}
-          />
-        </button>
-      </Tooltip>
+          <button
+            aria-label="Close"
+            className="btn btn--transparent unround-t unround-br color-gray py12 px12"
+            data-test="modal-close"
+            onClick={[MockFunction]}
+            type="button"
+          >
+            <Icon
+              inline={false}
+              name="close"
+              passthroughProps={Object {}}
+              size={18}
+            />
+          </button>
+        </Tooltip>
+      </div>
     </div>
-  </div>
-</Displaced>
+  </Displaced>
+</EventTrap>
 `;
 
 exports[`Modal basic small renders 1`] = `
-<Displaced
-  focusDialog={true}
-  getApplicationNode={[Function]}
-  mounted={true}
-  onExit={[MockFunction]}
-  titleText="Small modal title"
-  underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
-  underlayProps={
-    Object {
-      "data-popover-ignore-clicks": true,
+<EventTrap>
+  <Displaced
+    focusDialog={true}
+    getApplicationNode={[Function]}
+    mounted={true}
+    onExit={[MockFunction]}
+    titleText="Small modal title"
+    underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
+    underlayProps={
+      Object {
+        "data-popover-ignore-clicks": true,
+      }
     }
-  }
-  underlayStyle={
-    Object {
-      "zIndex": 1,
+    underlayStyle={
+      Object {
+        "zIndex": 1,
+      }
     }
-  }
->
-  <div
-    className="relative wmax-full w360 bg-white round px36 py36"
   >
-    <div>
-      Small modal body
-    </div>
     <div
-      className="mt24"
+      className="relative wmax-full w360 bg-white round px36 py36"
     >
-      <ModalActions
-        primaryAction={
-          Object {
-            "callback": [MockFunction],
-            "text": "Okay",
+      <div>
+        Small modal body
+      </div>
+      <div
+        className="mt24"
+      >
+        <ModalActions
+          primaryAction={
+            Object {
+              "callback": [MockFunction],
+              "text": "Okay",
+            }
           }
-        }
-      />
-    </div>
-    <div
-      className="absolute top right"
-    >
-      <Tooltip
-        alignment="center"
-        block={true}
-        coloring="light"
-        content="Close"
-        disabled={false}
-        maxWidth="medium"
-        padding="small"
-        placement="top"
-        respondsToClick={false}
-        textSize="s"
+        />
+      </div>
+      <div
+        className="absolute top right"
       >
-        <button
-          aria-label="Close"
-          className="btn btn--transparent unround-t unround-br color-gray py12 px12"
-          data-test="modal-close"
-          onClick={[MockFunction]}
-          type="button"
+        <Tooltip
+          alignment="center"
+          block={true}
+          coloring="light"
+          content="Close"
+          disabled={false}
+          maxWidth="medium"
+          padding="small"
+          placement="top"
+          respondsToClick={false}
+          textSize="s"
         >
-          <Icon
-            inline={false}
-            name="close"
-            passthroughProps={Object {}}
-            size={18}
-          />
-        </button>
-      </Tooltip>
+          <button
+            aria-label="Close"
+            className="btn btn--transparent unround-t unround-br color-gray py12 px12"
+            data-test="modal-close"
+            onClick={[MockFunction]}
+            type="button"
+          >
+            <Icon
+              inline={false}
+              name="close"
+              passthroughProps={Object {}}
+              size={18}
+            />
+          </button>
+        </Tooltip>
+      </div>
     </div>
-  </div>
-</Displaced>
+  </Displaced>
+</EventTrap>
 `;
 
 exports[`Modal no onExit renders 1`] = `
-<Displaced
-  focusDialog={true}
-  getApplicationNode={[Function]}
-  mounted={true}
-  titleText="No onExit passed as prop"
-  underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
-  underlayProps={
-    Object {
-      "data-popover-ignore-clicks": true,
+<EventTrap>
+  <Displaced
+    focusDialog={true}
+    getApplicationNode={[Function]}
+    mounted={true}
+    titleText="No onExit passed as prop"
+    underlayClass="bg-darken50 px12 py12 px60-mm py60-mm "
+    underlayProps={
+      Object {
+        "data-popover-ignore-clicks": true,
+      }
     }
-  }
-  underlayStyle={
-    Object {
-      "zIndex": 1,
+    underlayStyle={
+      Object {
+        "zIndex": 1,
+      }
     }
-  }
->
-  <div
-    className="relative wmax-full w360 bg-white round px36 py36"
   >
-    <div>
-      You can't close me
+    <div
+      className="relative wmax-full w360 bg-white round px36 py36"
+    >
+      <div>
+        You can't close me
+      </div>
     </div>
-  </div>
-</Displaced>
+  </Displaced>
+</EventTrap>
 `;
diff --git a/src/components/modal/__tests__/modal-test-cases.js b/src/components/modal/__tests__/modal-test-cases.js
index 22b73d5..57cc549 100644
--- a/src/components/modal/__tests__/modal-test-cases.js
+++ b/src/components/modal/__tests__/modal-test-cases.js
@@ -39,6 +39,90 @@ class ModalWrapper extends React.Component {
   }
 }
 
+class OuterModal extends React.Component {
+  state = {
+    modalOpen: false
+  };
+
+  toggleModal = () => {
+    this.setState(state => ({ modalOpen: !state.modalOpen }));
+  };
+
+  render() {
+    const modal = this.state.modalOpen && (
+      <Modal
+        accessibleTitle="Small modal title"
+        size="small"
+        primaryAction={{
+          text: 'Okay outer',
+          callback: safeSpy()
+        }}
+        onExit={this.toggleModal}
+      >
+        <InnerModal />
+      </Modal>
+    );
+    return (
+      <div>
+        <button
+          aria-label="Open modal"
+          type="button"
+          className="btn"
+          onClick={this.toggleModal}
+        >
+          Open modal
+        </button>
+        {modal}
+      </div>
+    );
+  }
+}
+
+class InnerModal extends React.Component {
+  state = {
+    modalOpen: false
+  };
+
+  toggleModal = () => {
+    this.setState(state => ({ modalOpen: !state.modalOpen }));
+  };
+
+  render() {
+    const modal = this.state.modalOpen && (
+      <Modal
+        alternateLocation="[data-gr-c-s-loaded]"
+        accessibleTitle="Small modal title"
+        size="small"
+        primaryAction={{
+          text: 'Okay inner',
+          callback: safeSpy()
+        }}
+        onExit={this.toggleModal}
+      >
+        <div>hi hello i am inner</div>
+      </Modal>
+    );
+    return (
+      <div>
+        <button
+          aria-label="Open modal"
+          type="button"
+          className="btn"
+          onClick={this.toggleModal}
+        >
+          Open modal
+        </button>
+        {modal}
+      </div>
+    );
+  }
+}
+
+testCases.nested = {
+  description: 'nested modals',
+  element: <OuterModal />
+};
+
 testCases.basicSmallDisplay = {
   description: 'basic small, display only',
   element: (
diff --git a/src/components/modal/__tests__/modal.test.js b/src/components/modal/__tests__/modal.test.js
index 39b5312..b821c2d 100644
--- a/src/components/modal/__tests__/modal.test.js
+++ b/src/components/modal/__tests__/modal.test.js
@@ -24,6 +24,12 @@ describe('Modal', () => {
 
       expect(testCase.props.onExit).toHaveBeenCalledTimes(1);
     });
+
+    test('allowEventBubbling disables event trapping', () => {
+      expect(wrapper.find('EventTrap').length).toBe(1);
+      wrapper.setProps({ allowEventBubbling: true });
+      expect(wrapper.find('EventTrap').length).toBe(0);
+    });
   });
 
   describe(noDisplayCases.basicLarge.description, () => {
diff --git a/src/components/popover/__tests__/__snapshots__/popover.test.js.snap b/src/components/popover/__tests__/__snapshots__/popover.test.js.snap
index 0d017d6..8d277fe 100644
--- a/src/components/popover/__tests__/__snapshots__/popover.test.js.snap
+++ b/src/components/popover/__tests__/__snapshots__/popover.test.js.snap
@@ -87,7 +87,7 @@ exports[`Popover dark renders 1`] = `
   mounted={true}
   onElement={[Function]}
   placement="right"
-  pointerColor="#273d56"
+  pointerColor="#0E2127"
   zIndex={1}
 >
   <div
@@ -99,7 +99,7 @@ exports[`Popover dark renders 1`] = `
     role="dialog"
     style={
       Object {
-        "backgroundColor": "#273d56",
+        "backgroundColor": "#0E2127",
       }
     }
     tabIndex={-1}
@@ -161,7 +161,7 @@ exports[`Popover warning renders 1`] = `
   mounted={true}
   onElement={[Function]}
   placement="right"
-  pointerColor="#FFF5A0"
+  pointerColor="#FBC997"
   zIndex={1}
 >
   <div
@@ -173,7 +173,7 @@ exports[`Popover warning renders 1`] = `
     role="dialog"
     style={
       Object {
-        "backgroundColor": "#FFF5A0",
+        "backgroundColor": "#FBC997",
       }
     }
     tabIndex={-1}