diff --git a/devtools/client/responsive.html/components/device-modal.js b/devtools/client/responsive.html/components/device-modal.js
index 123b8f2291cc..4514aa56c3d5 100644
--- a/devtools/client/responsive.html/components/device-modal.js
+++ b/devtools/client/responsive.html/components/device-modal.js
@@ -25,6 +25,10 @@ module.exports = createClass({
return {};
},
+ componentDidMount() {
+ window.addEventListener("keydown", this.onKeyDown, true);
+ },
+
componentWillReceiveProps(nextProps) {
let {
devices,
@@ -39,6 +43,10 @@ module.exports = createClass({
}
},
+ componentWillUnmount() {
+ window.removeEventListener("keydown", this.onKeyDown, true);
+ },
+
onDeviceCheckboxClick({ target }) {
this.setState({
[target.value]: !this.state[target.value]
@@ -78,18 +86,25 @@ module.exports = createClass({
onUpdateDeviceModalOpen(false);
},
+ onKeyDown(event) {
+ if (!this.props.devices.isModalOpen) {
+ return;
+ }
+ // Escape keycode
+ if (event.keyCode === 27) {
+ let {
+ onUpdateDeviceModalOpen
+ } = this.props;
+ onUpdateDeviceModalOpen(false);
+ }
+ },
+
render() {
let {
devices,
onUpdateDeviceModalOpen,
} = this.props;
- let modalClass = "device-modal container";
-
- if (!devices.isModalOpen) {
- modalClass += " hidden";
- }
-
const sortedDevices = {};
for (let type of devices.types) {
sortedDevices[type] = Object.assign([], devices[type])
@@ -98,54 +113,66 @@ module.exports = createClass({
return dom.div(
{
- className: modalClass,
+ id: "device-modal-wrapper",
+ className: this.props.devices.isModalOpen ? "opened" : "closed",
},
- dom.button({
- id: "device-close-button",
- className: "toolbar-button devtools-button",
- onClick: () => onUpdateDeviceModalOpen(false),
- }),
dom.div(
{
- className: "device-modal-content",
+ className: "device-modal container",
},
- devices.types.map(type => {
- return dom.div(
- {
- className: "device-type",
- key: type,
- },
- dom.header(
+ dom.button({
+ id: "device-close-button",
+ className: "toolbar-button devtools-button",
+ onClick: () => onUpdateDeviceModalOpen(false),
+ }),
+ dom.div(
+ {
+ className: "device-modal-content",
+ },
+ devices.types.map(type => {
+ return dom.div(
{
- className: "device-header",
+ className: "device-type",
+ key: type,
},
- type
- ),
- sortedDevices[type].map(device => {
- return dom.label(
+ dom.header(
{
- className: "device-label",
- key: device.name,
+ className: "device-header",
},
- dom.input({
- className: "device-input-checkbox",
- type: "checkbox",
- value: device.name,
- checked: this.state[device.name],
- onChange: this.onDeviceCheckboxClick,
- }),
- device.name
- );
- })
- );
- })
+ type
+ ),
+ sortedDevices[type].map(device => {
+ return dom.label(
+ {
+ className: "device-label",
+ key: device.name,
+ },
+ dom.input({
+ className: "device-input-checkbox",
+ type: "checkbox",
+ value: device.name,
+ checked: this.state[device.name],
+ onChange: this.onDeviceCheckboxClick,
+ }),
+ device.name
+ );
+ })
+ );
+ })
+ ),
+ dom.button(
+ {
+ id: "device-submit-button",
+ onClick: this.onDeviceModalSubmit,
+ },
+ getStr("responsive.done")
+ )
),
- dom.button(
+ dom.div(
{
- id: "device-submit-button",
- onClick: this.onDeviceModalSubmit,
- },
- getStr("responsive.done")
+ className: "modal-overlay",
+ onClick: () => onUpdateDeviceModalOpen(false),
+ }
)
);
},
diff --git a/devtools/client/responsive.html/index.css b/devtools/client/responsive.html/index.css
index 7275ac648e8d..0e7cd3b9f0f7 100644
--- a/devtools/client/responsive.html/index.css
+++ b/devtools/client/responsive.html/index.css
@@ -39,6 +39,7 @@
#root,
html, body {
+ height: 100%;
margin: 0;
}
@@ -47,12 +48,10 @@ html, body {
display: flex;
align-items: center;
flex-direction: column;
- height: 100vh;
-
- /* Snap to the top of the app when there isn't enough vertical space anymore
- to center the viewports (so we don't lose the global toolbar) */
- position: sticky;
- top: 0;
+ padding-top: 15px;
+ padding-bottom: 1%;
+ position: relative;
+ height: 100%;
}
/**
@@ -86,7 +85,7 @@ html, body {
color: var(--theme-body-color-alt);
border-radius: 2px;
box-shadow: var(--rdm-box-shadow);
- margin: 10% 0 30px 0;
+ margin: 0 0 15px 0;
padding: 4px 5px;
display: inline-flex;
-moz-user-select: none;
@@ -336,9 +335,33 @@ html, body {
* Device Modal
*/
+@keyframes fade-in-and-up {
+ 0% {
+ opacity: 0;
+ transform: translateY(5px);
+ }
+ 100% {
+ opacity: 1;
+ transform: translateY(0px);
+ }
+}
+
+@keyframes fade-down-and-out {
+ 0% {
+ opacity: 1;
+ transform: translateY(0px);
+ }
+ 100% {
+ opacity: 0;
+ transform: translateY(5px);
+ visibility: hidden;
+ }
+}
+
.device-modal {
border-radius: 2px;
box-shadow: var(--rdm-box-shadow);
+ display: none;
position: absolute;
margin: auto;
top: 0;
@@ -347,10 +370,31 @@ html, body {
right: 0;
width: 642px;
height: 612px;
+ z-index: 1;
}
-.device-modal.hidden {
- display: none;
+/* Handles the opening/closing of the modal */
+#device-modal-wrapper.opened .device-modal {
+ animation: fade-in-and-up 0.3s ease;
+ animation-fill-mode: forwards;
+ display: block;
+}
+
+#device-modal-wrapper.closed .device-modal {
+ animation: fade-down-and-out 0.3s ease;
+ animation-fill-mode: forwards;
+ display: block;
+}
+
+#device-modal-wrapper.opened .modal-overlay {
+ background-color: var(--theme-splitter-color);
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ z-index: 0;
+ opacity: 0.5;
}
.device-modal-content {