--- a/devtools/client/responsive.html/components/App.js
+++ b/devtools/client/responsive.html/components/App.js
@@ -26,17 +26,17 @@ const {
changeDevice,
changePixelRatio,
removeDeviceAssociation,
resizeViewport,
rotateViewport,
} = require("../actions/viewports");
const DeviceModal = createFactory(require("./DeviceModal"));
-const GlobalToolbar = createFactory(require("./GlobalToolbar"));
+const Toolbar = createFactory(require("./Toolbar"));
const Viewports = createFactory(require("./Viewports"));
const Types = require("../types");
class App extends Component {
static get propTypes() {
return {
devices: PropTypes.shape(Types.devices).isRequired,
@@ -211,17 +211,17 @@ class App extends Component {
if (devices.modalOpenedFromViewport !== null) {
deviceAdderViewportTemplate = viewports[devices.modalOpenedFromViewport];
}
return dom.div(
{
id: "app",
},
- GlobalToolbar({
+ Toolbar({
devices,
displayPixelRatio,
networkThrottling,
reloadConditions,
screenshot,
selectedDevice,
selectedPixelRatio,
touchSimulation,
--- a/devtools/client/responsive.html/components/DevicePixelRatioSelector.js
+++ b/devtools/client/responsive.html/components/DevicePixelRatioSelector.js
@@ -114,17 +114,17 @@ class DevicePixelRatioSelector extends P
let listContent = PIXEL_RATIO_PRESET.map(createVisibleOption);
if (state == Types.loadableState.LOADED) {
listContent = listContent.concat(hiddenOptions.map(createHiddenOption));
}
return dom.select(
{
- id: "global-device-pixel-ratio-selector",
+ id: "device-pixel-ratio-selector",
value: selectedPixelRatio.value || displayPixelRatio,
disabled: isDisabled,
onChange: this.onSelectChange,
onFocus: this.onFocusChange,
onBlur: this.onFocusChange,
className: selectorClass,
title: title
},
--- a/devtools/client/responsive.html/components/DeviceSelector.js
+++ b/devtools/client/responsive.html/components/DeviceSelector.js
@@ -67,17 +67,17 @@ class DeviceSelector extends PureCompone
}
}
}
options.sort(function(a, b) {
return a.name.localeCompare(b.name);
});
- let selectClass = "viewport-device-selector toolbar-dropdown";
+ let selectClass = "toolbar-dropdown";
if (selectedDevice) {
selectClass += " selected";
}
const state = devices.listState;
let listContent;
if (state == Types.loadableState.LOADED) {
@@ -112,16 +112,17 @@ class DeviceSelector extends PureCompone
value: "",
title: "",
disabled: true,
}, getStr("responsive.deviceListError"))];
}
return dom.select(
{
+ id: "device-selector",
className: selectClass,
value: selectedDevice,
title: selectedDevice,
onChange: this.onSelectChange,
disabled: (state !== Types.loadableState.LOADED),
},
...listContent
);
--- a/devtools/client/responsive.html/components/ReloadConditions.js
+++ b/devtools/client/responsive.html/components/ReloadConditions.js
@@ -21,17 +21,17 @@ class ReloadConditions extends PureCompo
render() {
const {
reloadConditions,
onChangeReloadCondition,
} = this.props;
return ToggleMenu({
- id: "global-reload-conditions-menu",
+ id: "reload-conditions-menu",
items: [
{
id: "touchSimulation",
label: getStr("responsive.reloadConditions.touchSimulation"),
checked: reloadConditions.touchSimulation,
},
{
id: "userAgent",
rename from devtools/client/responsive.html/components/GlobalToolbar.js
rename to devtools/client/responsive.html/components/Toolbar.js
--- a/devtools/client/responsive.html/components/GlobalToolbar.js
+++ b/devtools/client/responsive.html/components/Toolbar.js
@@ -10,17 +10,17 @@ const dom = require("devtools/client/sha
const { getStr } = require("../utils/l10n");
const Types = require("../types");
const DevicePixelRatioSelector = createFactory(require("./DevicePixelRatioSelector"));
const DeviceSelector = createFactory(require("./DeviceSelector"));
const NetworkThrottlingSelector = createFactory(require("devtools/client/shared/components/throttling/NetworkThrottlingSelector"));
const ReloadConditions = createFactory(require("./ReloadConditions"));
-class GlobalToolbar extends PureComponent {
+class Toolbar extends PureComponent {
static get propTypes() {
return {
devices: PropTypes.shape(Types.devices).isRequired,
displayPixelRatio: Types.pixelRatio.value.isRequired,
networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
reloadConditions: PropTypes.shape(Types.reloadConditions).isRequired,
screenshot: PropTypes.shape(Types.screenshot).isRequired,
selectedDevice: PropTypes.string.isRequired,
@@ -60,60 +60,63 @@ class GlobalToolbar extends PureComponen
} = this.props;
let touchButtonClass = "toolbar-button devtools-button";
if (touchSimulation.enabled) {
touchButtonClass += " checked";
}
return dom.header(
- {
- id: "global-toolbar",
- className: "container",
- },
+ { id: "toolbar" },
DeviceSelector({
devices,
selectedDevice,
viewportId: 0,
onChangeDevice,
onResizeViewport,
onUpdateDeviceModal,
}),
- NetworkThrottlingSelector({
- networkThrottling,
- onChangeNetworkThrottling,
- }),
- DevicePixelRatioSelector({
- devices,
- displayPixelRatio,
- selectedDevice,
- selectedPixelRatio,
- onChangePixelRatio,
- }),
- ReloadConditions({
- reloadConditions,
- onChangeReloadCondition,
- }),
- dom.button({
- id: "global-touch-simulation-button",
- className: touchButtonClass,
- title: (touchSimulation.enabled ?
- getStr("responsive.disableTouch") : getStr("responsive.enableTouch")),
- onClick: () => onChangeTouchSimulation(!touchSimulation.enabled),
- }),
- dom.button({
- id: "global-screenshot-button",
- className: "toolbar-button devtools-button",
- title: getStr("responsive.screenshot"),
- onClick: onScreenshot,
- disabled: screenshot.isCapturing,
- }),
- dom.button({
- id: "global-exit-button",
- className: "toolbar-button devtools-button",
- title: getStr("responsive.exit"),
- onClick: onExit,
- })
+ dom.div(
+ { id: "toolbar-center-controls" },
+ DevicePixelRatioSelector({
+ devices,
+ displayPixelRatio,
+ selectedDevice,
+ selectedPixelRatio,
+ onChangePixelRatio,
+ }),
+ NetworkThrottlingSelector({
+ networkThrottling,
+ onChangeNetworkThrottling,
+ }),
+ dom.button({
+ id: "touch-simulation-button",
+ className: touchButtonClass,
+ title: (touchSimulation.enabled ?
+ getStr("responsive.disableTouch") : getStr("responsive.enableTouch")),
+ onClick: () => onChangeTouchSimulation(!touchSimulation.enabled),
+ })
+ ),
+ dom.div(
+ { id: "toolbar-end-controls" },
+ dom.button({
+ id: "screenshot-button",
+ className: "toolbar-button devtools-button",
+ title: getStr("responsive.screenshot"),
+ onClick: onScreenshot,
+ disabled: screenshot.isCapturing,
+ }),
+ ReloadConditions({
+ reloadConditions,
+ onChangeReloadCondition,
+ }),
+ dom.button({
+ id: "exit-button",
+ className: "toolbar-button devtools-button",
+ title: getStr("responsive.exit"),
+ onClick: onExit,
+ })
+ )
);
}
}
-module.exports = GlobalToolbar;
+module.exports = Toolbar;
--- a/devtools/client/responsive.html/components/Viewports.js
+++ b/devtools/client/responsive.html/components/Viewports.js
@@ -28,29 +28,49 @@ class Viewports extends Component {
screenshot,
viewports,
onBrowserMounted,
onContentResize,
onRemoveDeviceAssociation,
onResizeViewport,
} = this.props;
- return dom.div(
- {
- id: "viewports",
- },
- viewports.map((viewport, i) => {
- return ResizableViewport({
- key: viewport.id,
- screenshot,
- swapAfterMount: i == 0,
- viewport,
- onBrowserMounted,
- onContentResize,
- onRemoveDeviceAssociation,
- onResizeViewport,
- });
- })
+ const viewportSize = window.getViewportSize();
+ // The viewport may not have been created yet. Default to justify-content: center
+ // for the container.
+ let justifyContent = "center";
+
+ // If the RDM viewport is bigger than the window's inner width, set the container's
+ // justify-content to start so that the left-most viewport is visible when there's
+ // horizontal overflow. That is when the horizontal space become smaller than the
+ // viewports and a scrollbar appears, then the first viewport will still be visible.
+ if (viewportSize && viewportSize.width > window.innerWidth) {
+ justifyContent = "start";
+ }
+
+ return (
+ dom.div(
+ {
+ id: "viewports-container",
+ style: {
+ justifyContent,
+ },
+ },
+ dom.div({ id: "viewports" },
+ viewports.map((viewport, i) => {
+ return ResizableViewport({
+ key: viewport.id,
+ screenshot,
+ swapAfterMount: i == 0,
+ viewport,
+ onBrowserMounted,
+ onContentResize,
+ onRemoveDeviceAssociation,
+ onResizeViewport,
+ });
+ })
+ )
+ )
);
}
}
module.exports = Viewports;
--- a/devtools/client/responsive.html/components/moz.build
+++ b/devtools/client/responsive.html/components/moz.build
@@ -6,15 +6,15 @@
DevToolsModules(
'App.js',
'Browser.js',
'DeviceAdder.js',
'DeviceModal.js',
'DevicePixelRatioSelector.js',
'DeviceSelector.js',
- 'GlobalToolbar.js',
'ReloadConditions.js',
'ResizableViewport.js',
'ToggleMenu.js',
+ 'Toolbar.js',
'ViewportDimension.js',
'Viewports.js',
)
--- a/devtools/client/responsive.html/index.css
+++ b/devtools/client/responsive.html/index.css
@@ -28,34 +28,30 @@
* {
box-sizing: border-box;
}
:root,
input,
select,
button {
- font-size: 11px;
+ font-size: 12px;
}
html,
body,
#root {
height: 100%;
- margin: 0;
+ overflow: hidden;
}
#app {
- /* Center the viewports container */
display: flex;
- align-items: center;
flex-direction: column;
- padding-top: 15px;
- padding-bottom: 1%;
- position: relative;
+ width: 100%;
height: 100%;
}
/**
* Common styles for shared components
*/
.container {
@@ -141,17 +137,17 @@ select > option.divider {
position: relative;
}
.devtools-toggle-menu .devtools-menu {
display: none;
flex-direction: column;
align-items: start;
position: absolute;
- left: 0;
+ right: 0;
top: 100%;
z-index: 1;
padding: 5px;
border-radius: 2px;
background-color: var(--theme-toolbar-background);
box-shadow: var(--rdm-box-shadow);
}
@@ -162,128 +158,145 @@ select > option.divider {
.devtools-toggle-menu .devtools-menu-item {
display: flex;
align-items: center;
}
/**
* Common background for dropdowns like select and toggle menu
*/
+
.toolbar-dropdown,
.toolbar-dropdown.devtools-button,
.toolbar-dropdown.devtools-button:hover:not(:empty):not(:disabled):not(.checked) {
background-color: var(--theme-toolbar-background);
background-image: var(--viewport-selection-arrow);
background-position: 100% 50%;
background-repeat: no-repeat;
background-size: 7px;
-moz-context-properties: fill;
fill: currentColor;
}
+.toolbar-dropdown {
+ background-position-x: right 5px;
+ border-right: 1px solid var(--theme-splitter-color);
+ padding-right: 15px;
+}
+
/**
- * Global Toolbar
+ * Toolbar
*/
-#global-toolbar {
- color: var(--theme-body-color-alt);
- border-radius: 2px;
- box-shadow: var(--rdm-box-shadow);
- margin: 0 0 15px 0;
- padding: 4px 5px;
- display: inline-flex;
- align-items: center;
+#toolbar {
+ background-color: var(--theme-toolbar-background);
+ border-bottom: 1px solid var(--theme-splitter-color);
+ display: grid;
+ grid-template-columns: min-content auto min-content;
+ width: 100%;
+ min-height: 29px;
-moz-user-select: none;
}
-#global-toolbar > .toolbar-button:first-of-type {
+#toolbar > .toolbar-button:first-of-type {
margin-inline-start: 8px;
}
-#global-toolbar > .toolbar-button::before {
+#toolbar > .toolbar-button::before {
width: 12px;
height: 12px;
background-size: cover;
}
-#global-toolbar .toolbar-dropdown {
- background-position-x: right 5px;
- border-right: 1px solid var(--theme-splitter-color);
- padding-right: 15px;
- /* padding-left: 0; */
+#device-selector {
+ border-right: none;
}
-#global-touch-simulation-button::before {
+#toolbar-center-controls,
+#toolbar-end-controls {
+ display: flex;
+ align-items: center;
+}
+
+#toolbar-center-controls {
+ justify-self: center;
+}
+
+#touch-simulation-button::before {
background-image: url("./images/touch-events.svg");
}
-#global-screenshot-button::before {
+#screenshot-button::before {
background-image: url("./images/screenshot.svg");
}
-#global-exit-button::before {
+#exit-button::before {
background-image: url("chrome://devtools/skin/images/close.svg");
}
-#global-screenshot-button:disabled {
+#screenshot-button:disabled {
filter: var(--theme-icon-checked-filter);
opacity: 1 !important;
}
-#global-network-throttling-selector {
+#network-throttling-selector {
height: 15px;
padding-left: 0;
width: 103px;
}
-#global-device-pixel-ratio-selector {
+#device-pixel-ratio-selector {
-moz-user-select: none;
color: var(--viewport-color);
height: 15px;
/* `max-width` is here to keep the UI compact if the device pixel ratio changes to a
repeating decimal value. This can happen if you zoom the UI (Cmd + Plus / Minus on
macOS for example). */
max-width: 8em;
}
-#global-device-pixel-ratio-selector.focused,
-#global-device-pixel-ratio-selector:not(.disabled):hover {
+#device-pixel-ratio-selector.focused,
+#device-pixel-ratio-selector:not(.disabled):hover {
color: var(--viewport-hover-color);
}
-#global-device-pixel-ratio-selector:focus {
+#device-pixel-ratio-selector:focus {
color: var(--viewport-active-color);
}
-#global-device-pixel-ratio-selector.selected {
+#device-pixel-ratio-selector.selected {
color: var(--viewport-active-color);
}
-#global-device-pixel-ratio-selector > option {
+#device-pixel-ratio-selector > option {
padding: 5px;
}
.viewport-rotate-button {
position: absolute;
right: 0;
}
.viewport-rotate-button::before {
background-image: url("./images/rotate-viewport.svg");
}
+#viewports-container {
+ display: flex;
+ justify-content: center;
+ overflow: auto;
+ height: 100%;
+ width: 100%;
+}
+
#viewports {
- /* Make sure left-most viewport is visible when there's horizontal overflow.
- That is, when the horizontal space become smaller than the viewports and a
- scrollbar appears, then the first viewport will still be visible */
- position: sticky;
- left: 0;
/* Individual viewports are inline elements, make sure they stay on a single
line */
white-space: nowrap;
+ padding-top: 30px;
}
/**
* Viewport Container
*/
.viewport {
display: inline-block;
--- a/devtools/client/responsive.html/index.js
+++ b/devtools/client/responsive.html/index.js
@@ -132,17 +132,22 @@ window.addInitialViewport = ({ uri, user
console.error(e);
}
};
/**
* Called by manager.js when tests want to check the viewport size.
*/
window.getViewportSize = () => {
- const { width, height } = bootstrap.store.getState().viewports[0];
+ const { viewports } = bootstrap.store.getState();
+ if (!viewports.length) {
+ return null;
+ }
+
+ const { width, height } = viewports[0];
return { width, height };
};
/**
* Called by manager.js to set viewport size from tests, GCLI, etc.
*/
window.setViewportSize = ({ width, height }) => {
try {
--- a/devtools/client/responsive.html/test/browser/browser_network_throttling.js
+++ b/devtools/client/responsive.html/test/browser/browser_network_throttling.js
@@ -26,17 +26,17 @@ addRDMTask(TEST_URL, async function({ ui
// Test switching back to no throttling
await selectNetworkThrottling(ui, "No throttling");
testNetworkThrottlingSelectorLabel(ui, "No throttling");
await testNetworkThrottlingState(ui, null);
});
function testNetworkThrottlingSelectorLabel(ui, expected) {
- const selector = "#global-network-throttling-selector";
+ const selector = "#network-throttling-selector";
const select = ui.toolWindow.document.querySelector(selector);
is(select.selectedOptions[0].textContent, expected,
`Select label should be changed to ${expected}`);
}
var testNetworkThrottlingState = async function(ui, expected) {
const state = await ui.emulationFront.getNetworkThrottling();
Assert.deepEqual(state, expected, "Network throttling state should be " +
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -268,17 +268,17 @@ const selectDevice = (ui, value) => Prom
changeSelectValue(ui, ".viewport-device-selector", value)
]);
const selectDevicePixelRatio = (ui, value) =>
changeSelectValue(ui, "#global-device-pixel-ratio-selector", value);
const selectNetworkThrottling = (ui, value) => Promise.all([
once(ui, "network-throttling-changed"),
- changeSelectValue(ui, "#global-network-throttling-selector", value)
+ changeSelectValue(ui, "#network-throttling-selector", value)
]);
function getSessionHistory(browser) {
return ContentTask.spawn(browser, {}, async function() {
/* eslint-disable no-undef */
const { SessionHistory } =
ChromeUtils.import("resource://gre/modules/sessionstore/SessionHistory.jsm", {});
return SessionHistory.collect(docShell);
--- a/devtools/client/shared/components/throttling/NetworkThrottlingSelector.js
+++ b/devtools/client/shared/components/throttling/NetworkThrottlingSelector.js
@@ -94,17 +94,17 @@ class NetworkThrottlingSelector extends
},
profile.id
);
}),
];
return dom.select(
{
- id: "global-network-throttling-selector",
+ id: "network-throttling-selector",
className: selectClass,
value: selectedProfile,
onChange: this.onSelectChange,
},
...listContent
);
}
}