Bug 1539813 - Uplift Debugger UI improvements. r=dwalsh a=pascalc l10n=flod
authorDavid Walsh <davidwalsh83@gmail.com>
Fri, 29 Mar 2019 15:00:00 +0200
changeset 525920 32f822dd45b8c243058756713840819b67b59afd
parent 525919 251103ed375f19184a5d2c1a5c0b64ed9dbb9307
child 525921 0fcf234877a7b52c1427b643386ef56892798991
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdwalsh, pascalc
bugs1539813, 1538164, 1536216, 1536113, 1535095, 1536114
milestone67.0
Bug 1539813 - Uplift Debugger UI improvements. r=dwalsh a=pascalc l10n=flod Bug 1538164 - [release 130] added no sources message in Sources Pane (#7978). Bug 1538164 - [release 130] [Log Point] Fix log point context menu accelerator (#8115). Bug 1536216 - Redesign map scopes pane r=jlast Bug 1536113 - Column Breakpoints have a blue background. r=davidwalsh Bug 1535095 - Hidden column breakpoints are shown. r=davidwalsh Bug 1536114 - Update columnn breakpoint colors for debugger r=jlast
devtools/client/debugger/new/dist/debugger.css
devtools/client/debugger/new/src/actions/navigation.js
devtools/client/debugger/new/src/actions/tests/navigation.spec.js
devtools/client/debugger/new/src/client/firefox/commands.js
devtools/client/debugger/new/src/components/Editor/Breakpoints.css
devtools/client/debugger/new/src/components/Editor/ColumnBreakpoint.js
devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
devtools/client/debugger/new/src/components/Editor/Editor.css
devtools/client/debugger/new/src/components/Editor/index.js
devtools/client/debugger/new/src/components/Editor/menus/breakpoints.js
devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTree.spec.js
devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTree.spec.js.snap
devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js
devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.css
devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js
devtools/client/debugger/new/src/components/SecondaryPanes/index.js
devtools/client/debugger/new/src/components/ShortcutsModal.js
devtools/client/debugger/new/src/components/test/__snapshots__/ShortcutsModal.spec.js.snap
devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.js
devtools/client/locales/en-US/debugger.properties
--- a/devtools/client/debugger/new/dist/debugger.css
+++ b/devtools/client/debugger/new/dist/debugger.css
@@ -2665,69 +2665,16 @@ menuseparator {
 .add-to-expression-bar .expression-to-save-button {
   font-size: 14px;
   color: var(--theme-comment);
 }
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
-.column-breakpoint {
-  display: inline;
-  padding-inline-start: 1px;
-  padding-inline-end: 3px;
-}
-
-.column-breakpoint:hover {
-  background-color: transparent;
-}
-
-.column-breakpoint svg {
-  display: inline-block;
-  cursor: pointer;
-  height: 13px;
-  width: 11px;
-  vertical-align: top;
-  fill: var(--blue-40);
-  stroke: var(--blue-60);
-}
-
-.column-breakpoint.disabled svg {
-  fill-opacity: 0.7;
-  stroke-opacity: 0.7;
-}
-
-.column-breakpoint.has-condition svg {
-  fill: var(--theme-graphs-yellow);
-  stroke: var(--theme-graphs-orange);
-}
-
-.column-breakpoint.has-log svg {
-  fill: var(--theme-graphs-purple);
-  stroke: var(--purple-60);
-}
-
-.theme-dark .column-breakpoint.active svg {
-  fill: var(--blue-55);
-  stroke: var(--blue-40);
-}
-
-.theme-dark .column-breakpoint.disabled svg {
-  fill: var(--blue-50);
-  stroke: var(--blue-60);
-  fill-opacity: 0.5;
-}
-
-.img.column-marker {
-  background-image: url("resource://devtools/client/debugger/new/images/column-marker.svg");
-}
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
-
 .conditional-breakpoint-panel {
   cursor: initial;
   margin: 1em 0;
   position: relative;
   display: flex;
   align-items: center;
   background: var(--theme-toolbar-background);
   border-top: 1px solid var(--theme-splitter-color);
@@ -2798,64 +2745,24 @@ menuseparator {
   top: var(--editor-header-height);
   left: 0px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
 
-.theme-light {
-  --gutter-hover-background-color: #dde1e4;
-  --breakpoint-fill: var(--blue-50);
-  --breakpoint-stroke: var(--blue-60);
-}
-
-.theme-dark {
-  --gutter-hover-background-color: #414141;
-  --breakpoint-fill: var(--blue-55);
-  --breakpoint-stroke: var(--blue-40);
-}
-
 .theme-light .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-40);
 }
 
 .theme-dark .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-50);
 }
 
-.new-breakpoint .CodeMirror-linenumber {
-  pointer-events: none;
-}
-
-:not(.empty-line):not(.new-breakpoint)
-  > .CodeMirror-gutter-wrapper:hover
-  > .CodeMirror-linenumber::after {
-  content: "";
-  position: absolute;
-  /* paint below the number */
-  z-index: -1;
-  top: 0;
-  left: 0;
-  right: -7px;
-  bottom: 0;
-  height: 15px;
-  background-color: var(--gutter-hover-background-color);
-  mask: url("resource://devtools/client/debugger/new/images/breakpoint.svg") no-repeat;
-  mask-size: auto 15px;
-  mask-position: right;
-}
-
-.editor-wrapper .breakpoints {
-  position: absolute;
-  top: 0;
-  left: 0;
-}
-
 .function-search {
   max-height: 300px;
   overflow: hidden;
 }
 
 .function-search .results {
   height: auto;
 }
@@ -2863,60 +2770,16 @@ html[dir="rtl"] .editor-mount {
 .editor.hit-marker {
   height: 15px;
 }
 
 .editor-wrapper .highlight-lines {
   background: var(--theme-selection-background-hover);
 }
 
-.editor.new-breakpoint svg {
-  fill: var(--breakpoint-fill);
-  stroke: var(--breakpoint-stroke);
-  width: 60px;
-  height: 15px;
-  position: absolute;
-  top: 0px;
-  right: -4px;
-}
-
-.inline-bp {
-  background-color: #9ddfff;
-  width: 20px;
-  padding: 0px 5px;
-  margin: 0px 4px;
-  border-radius: 5px;
-  border-color: blue;
-  border: 1px solid #00b6ff;
-}
-
-.editor .breakpoint {
-  position: absolute;
-  right: -2px;
-}
-
-.editor.new-breakpoint.folding-enabled svg {
-  right: -16px;
-}
-
-.new-breakpoint.has-condition .CodeMirror-gutter-wrapper svg {
-  fill: var(--theme-graphs-yellow);
-  stroke: var(--theme-graphs-orange);
-}
-
-.new-breakpoint.has-log .CodeMirror-gutter-wrapper svg {
-  fill: var(--theme-graphs-purple);
-  stroke: var(--purple-60);
-}
-
-.editor.new-breakpoint.breakpoint-disabled svg {
-  fill-opacity: 0.7;
-  stroke-opacity: 0.7;
-}
-
 .CodeMirror {
   width: 100%;
   height: 100%;
 }
 
 .editor-wrapper .editor-mount {
   width: 100%;
   background-color: var(--theme-body-background);
@@ -2942,17 +2805,17 @@ html[dir="rtl"] .editor-mount {
   z-index: 0;
 }
 
 .theme-dark .editor-wrapper .CodeMirror-line .cm-comment {
   color: var(--theme-comment);
 }
 
 .debug-expression,
-.new-debug-line .column-breakpoint {
+.debug-expression ~ .CodeMirror-widget {
   background-color: var(--debug-expression-background);
 }
 
 debug-expression-error {
   background-color: var(--debug-expression-error-background);
 }
 
 .new-debug-line .CodeMirror-line {
@@ -3012,16 +2875,170 @@ debug-expression-error {
 
 .download-anchor {
   display: none;
 }
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
+ .theme-light {
+  --gutter-hover-background-color: #dde1e4;
+
+  --breakpoint-fill: var(--blue-50);
+  --breakpoint-stroke: var(--blue-60);
+
+  --breakpoint-disabled-fill: var(--blue-55);
+  --breakpoint-disabled-stroke: var(--blue-55);
+}
+
+.theme-dark {
+  --gutter-hover-background-color: #414141;
+
+  --breakpoint-fill: var(--blue-55);
+  --breakpoint-stroke: var(--blue-40);
+
+  --breakpoint-disabled-fill: var(--blue-55);
+  --breakpoint-disabled-stroke: var(--blue-55);
+}
+
+.theme-light, .theme-dark {
+  --logpoint-fill: var(--theme-graphs-purple);
+  --logpoint-stroke: var(--purple-60);
+  --breakpoint-condition-fill: var(--theme-graphs-yellow);
+  --breakpoint-condition-stroke: var(--theme-graphs-orange);
+  --breakpoint-inactive-opacity: 0.3;
+  --breakpoint-disabled-opacity: 0.6;
+}
+
+/* Standard gutter breakpoints */
+.editor-wrapper .breakpoints {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+
+.new-breakpoint .CodeMirror-linenumber {
+  pointer-events: none;
+}
+
+:not(.empty-line):not(.new-breakpoint)
+  > .CodeMirror-gutter-wrapper:hover
+  > .CodeMirror-linenumber::after {
+  content: "";
+  position: absolute;
+  /* paint below the number */
+  z-index: -1;
+  top: 0;
+  left: 0;
+  right: -7px;
+  bottom: 0;
+  height: 15px;
+  background-color: var(--gutter-hover-background-color);
+  mask: url("resource://devtools/client/debugger/new/images/breakpoint.svg") no-repeat;
+  mask-size: auto 15px;
+  mask-position: right;
+}
+
+.editor.new-breakpoint svg {
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  width: 60px;
+  height: 15px;
+  position: absolute;
+  top: 0px;
+  right: -4px;
+}
+
+.editor .breakpoint {
+  position: absolute;
+  right: -2px;
+}
+
+.editor.new-breakpoint.folding-enabled svg {
+  right: -16px;
+}
+
+.new-breakpoint.has-condition .CodeMirror-gutter-wrapper svg {
+  fill: var(--breakpoint-condition-fill);
+  stroke: var(--breakpoint-condition-stroke);
+}
+
+.new-breakpoint.has-log .CodeMirror-gutter-wrapper svg {
+  fill: var(--logpoint-fill);
+  stroke: var(--logpoint-stroke);
+}
+
+.editor.new-breakpoint.breakpoint-disabled svg {
+  fill-opacity: var(--breakpoint-disabled-opacity);
+  stroke-opacity: var(--breakpoint-disabled-opacity);
+}
+
+/* Columnn breakpoints */
+.column-breakpoint {
+  display: inline;
+  padding-inline-start: 1px;
+  padding-inline-end: 1px;
+}
+
+.column-breakpoint:hover {
+  background-color: transparent;
+}
+
+.column-breakpoint svg {
+  display: inline-block;
+  cursor: pointer;
+  height: 13px;
+  width: 11px;
+  vertical-align: top;
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  fill-opacity: var(--breakpoint-inactive-opacity);
+  stroke-opacity: var(--breakpoint-inactive-opacity);
+}
+
+.column-breakpoint.active svg {
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  fill-opacity: 1;
+  stroke-opacity: 1;
+}
+
+.column-breakpoint.disabled svg {
+  fill-opacity: var(--breakpoint-disabled-opacity);
+  stroke-opacity: var(--breakpoint-disabled-opacity);
+}
+
+.column-breakpoint.has-log.disabled svg {
+  fill-opacity: 0.5;
+  stroke-opacity: 0.5;
+}
+
+.column-breakpoint.disabled:not(.has-condition):not(.has-log) svg {
+  fill: var(--breakpoint-disabled-fill);
+  stroke: var(--breakpoint-disabled-stroke);
+}
+
+.column-breakpoint.has-condition svg {
+  fill: var(--breakpoint-condition-fill);
+  stroke: var(--breakpoint-condition-stroke);
+}
+
+.column-breakpoint.has-log svg {
+  fill: var(--logpoint-fill);
+  stroke: var(--logpoint-stroke);
+}
+
+.img.column-marker {
+  background-image: url("resource://devtools/client/debugger/new/images/column-marker.svg");
+}
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+
 .cm-highlight {
   position: relative;
 }
 
 .cm-highlight::before {
   position: absolute;
   border-top-style: solid;
   border-bottom-style: solid;
@@ -4004,50 +4021,35 @@ html[dir="rtl"] .event-listeners-content
 	margin-inline-start: 0px;
 	margin-top: 0px;
 	margin-bottom: 0px;
 }
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
-.scopes-content .toggle-map-scopes {
-  border-bottom: 1px solid var(--theme-splitter-color);
-  margin-bottom: 3px;
-  margin-left: 10px;
-  padding: 0.5em 0;
-}
-
-.scopes-content .toggle-map-scopes input {
-  padding-inline-start: 2px;
-  margin-inline-start: 0;
-  vertical-align: text-bottom;
-}
-
-.scopes-content .toggle-map-scopes-label {
-  padding-inline-start: 2px;
-  padding-inline-end: 8px;
-  cursor: default;
-  flex-grow: 1;
-  -moz-user-select: none;
+ .secondary-panes .map-scopes-header {
+  padding-inline-end: 3px;
+ }
+
+.secondary-panes .header-buttons .img.shortcuts {
+  width: 14px;
+  height: 14px;
+  /* Better vertical centering of the icon */
+  margin-top: -2px;
 }
 
 .scopes-content .toggle-map-scopes a.mdn {
-  padding-inline-end: 10px;
+  padding-inline-start: 3px;
 }
 
 .scopes-content .toggle-map-scopes .img.shortcuts {
   background: var(--theme-comment);
 }
 
-.scopes-content .toggle-map-scopes {
-  display: flex;
-  align-items: center;
-}
-
 .object-node.default-property {
   opacity: 0.6;
 }
 
 .object-node {
   padding-left: 4px;
 }
 
--- a/devtools/client/debugger/new/src/actions/navigation.js
+++ b/devtools/client/debugger/new/src/actions/navigation.js
@@ -36,16 +36,17 @@ export function willNavigate(event: Obje
   return function({ dispatch, getState, client, sourceMaps }: ThunkArgs) {
     sourceMaps.clearSourceMaps();
     clearWasmStates();
     clearDocuments();
     clearSymbols();
     clearASTs();
     clearScopes();
     clearSources();
+    client.detachWorkers();
     dispatch(navigate(event.url));
   };
 }
 
 export function navigate(url: string) {
   return async function({ dispatch, getState }: ThunkArgs) {
     sourceQueue.clear();
     const thread = getMainThread(getState());
--- a/devtools/client/debugger/new/src/actions/tests/navigation.spec.js
+++ b/devtools/client/debugger/new/src/actions/tests/navigation.spec.js
@@ -22,17 +22,18 @@ const {
   getFileSearchResults
 } = selectors;
 
 const threadClient = {
   sourceContents: async () => ({
     source: "function foo1() {\n  const foo = 5; return foo;\n}",
     contentType: "text/javascript"
   }),
-  getBreakpointPositions: async () => ({})
+  getBreakpointPositions: async () => ({}),
+  detachWorkers: () => {}
 };
 
 describe("navigation", () => {
   it("connect sets the debuggeeUrl", async () => {
     const { dispatch, getState } = createStore({
       fetchWorkers: () => Promise.resolve([]),
       getMainThread: () => "FakeThread"
     });
@@ -62,37 +63,37 @@ describe("navigation", () => {
 
     results = getTextSearchResults(getState());
     expect(results).toHaveLength(0);
     expect(getTextSearchQuery(getState())).toEqual("");
     expect(getTextSearchStatus(getState())).toEqual("INITIAL");
   });
 
   it("navigation removes activeSearch 'project' value", async () => {
-    const { dispatch, getState } = createStore();
+    const { dispatch, getState } = createStore(threadClient);
     dispatch(actions.setActiveSearch("project"));
     expect(getActiveSearch(getState())).toBe("project");
 
     await dispatch(actions.willNavigate("will-navigate"));
     expect(getActiveSearch(getState())).toBe(null);
   });
 
   it("navigation clears the file-search query", async () => {
-    const { dispatch, getState } = createStore();
+    const { dispatch, getState } = createStore(threadClient);
 
     dispatch(actions.setFileSearchQuery("foobar"));
     expect(getFileSearchQuery(getState())).toBe("foobar");
 
     await dispatch(actions.willNavigate("will-navigate"));
 
     expect(getFileSearchQuery(getState())).toBe("");
   });
 
   it("navigation clears the file-search results", async () => {
-    const { dispatch, getState } = createStore();
+    const { dispatch, getState } = createStore(threadClient);
 
     const searchResults = [{ line: 1, ch: 3 }, { line: 3, ch: 2 }];
     dispatch(actions.updateSearchResults(2, 3, searchResults));
     expect(getFileSearchResults(getState())).toEqual({
       count: 2,
       index: 2,
       matchIndex: 1,
       matches: searchResults
@@ -104,16 +105,16 @@ describe("navigation", () => {
       count: 0,
       index: -1,
       matchIndex: -1,
       matches: []
     });
   });
 
   it("navigation removes activeSearch 'file' value", async () => {
-    const { dispatch, getState } = createStore();
+    const { dispatch, getState } = createStore(threadClient);
     dispatch(actions.setActiveSearch("file"));
     expect(getActiveSearch(getState())).toBe("file");
 
     await dispatch(actions.willNavigate("will-navigate"));
     expect(getActiveSearch(getState())).toBe(null);
   });
 });
--- a/devtools/client/debugger/new/src/client/firefox/commands.js
+++ b/devtools/client/debugger/new/src/client/firefox/commands.js
@@ -182,16 +182,22 @@ function locationKey(location: Breakpoin
   const sourceId = location.sourceId || "";
   return `${(sourceUrl: any)}:${sourceId}:${line}:${(column: any)}`;
 }
 
 function waitForWorkers(shouldWait: boolean) {
   shouldWaitForWorkers = shouldWait;
 }
 
+function detachWorkers() {
+  for (const thread of listWorkerThreadClients()) {
+    thread.detach();
+  }
+}
+
 function maybeGenerateLogGroupId(options) {
   if (options.logValue && tabTarget.traits && tabTarget.traits.canRewind) {
     return { ...options, logGroupId: `logGroup-${Math.random()}` };
   }
   return options;
 }
 
 function maybeClearLogpoint(location: BreakpointLocation) {
@@ -480,12 +486,13 @@ const clientCommands = {
   pauseOnExceptions,
   fetchSources,
   registerSourceActor,
   fetchWorkers,
   getMainThread,
   sendPacket,
   setSkipPausing,
   setEventListenerBreakpoints,
-  waitForWorkers
+  waitForWorkers,
+  detachWorkers
 };
 
 export { setupCommands, clientCommands };
new file mode 100644
--- /dev/null
+++ b/devtools/client/debugger/new/src/components/Editor/Breakpoints.css
@@ -0,0 +1,154 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
+
+ .theme-light {
+  --gutter-hover-background-color: #dde1e4;
+
+  --breakpoint-fill: var(--blue-50);
+  --breakpoint-stroke: var(--blue-60);
+
+  --breakpoint-disabled-fill: var(--blue-55);
+  --breakpoint-disabled-stroke: var(--blue-55);
+}
+
+.theme-dark {
+  --gutter-hover-background-color: #414141;
+
+  --breakpoint-fill: var(--blue-55);
+  --breakpoint-stroke: var(--blue-40);
+
+  --breakpoint-disabled-fill: var(--blue-55);
+  --breakpoint-disabled-stroke: var(--blue-55);
+}
+
+.theme-light, .theme-dark {
+  --logpoint-fill: var(--theme-graphs-purple);
+  --logpoint-stroke: var(--purple-60);
+  --breakpoint-condition-fill: var(--theme-graphs-yellow);
+  --breakpoint-condition-stroke: var(--theme-graphs-orange);
+  --breakpoint-inactive-opacity: 0.3;
+  --breakpoint-disabled-opacity: 0.6;
+}
+
+/* Standard gutter breakpoints */
+.editor-wrapper .breakpoints {
+  position: absolute;
+  top: 0;
+  left: 0;
+}
+
+.new-breakpoint .CodeMirror-linenumber {
+  pointer-events: none;
+}
+
+:not(.empty-line):not(.new-breakpoint)
+  > .CodeMirror-gutter-wrapper:hover
+  > .CodeMirror-linenumber::after {
+  content: "";
+  position: absolute;
+  /* paint below the number */
+  z-index: -1;
+  top: 0;
+  left: 0;
+  right: -7px;
+  bottom: 0;
+  height: 15px;
+  background-color: var(--gutter-hover-background-color);
+  mask: url(/images/breakpoint.svg) no-repeat;
+  mask-size: auto 15px;
+  mask-position: right;
+}
+
+.editor.new-breakpoint svg {
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  width: 60px;
+  height: 15px;
+  position: absolute;
+  top: 0px;
+  right: -4px;
+}
+
+.editor .breakpoint {
+  position: absolute;
+  right: -2px;
+}
+
+.editor.new-breakpoint.folding-enabled svg {
+  right: -16px;
+}
+
+.new-breakpoint.has-condition .CodeMirror-gutter-wrapper svg {
+  fill: var(--breakpoint-condition-fill);
+  stroke: var(--breakpoint-condition-stroke);
+}
+
+.new-breakpoint.has-log .CodeMirror-gutter-wrapper svg {
+  fill: var(--logpoint-fill);
+  stroke: var(--logpoint-stroke);
+}
+
+.editor.new-breakpoint.breakpoint-disabled svg {
+  fill-opacity: var(--breakpoint-disabled-opacity);
+  stroke-opacity: var(--breakpoint-disabled-opacity);
+}
+
+/* Columnn breakpoints */
+.column-breakpoint {
+  display: inline;
+  padding-inline-start: 1px;
+  padding-inline-end: 1px;
+}
+
+.column-breakpoint:hover {
+  background-color: transparent;
+}
+
+.column-breakpoint svg {
+  display: inline-block;
+  cursor: pointer;
+  height: 13px;
+  width: 11px;
+  vertical-align: top;
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  fill-opacity: var(--breakpoint-inactive-opacity);
+  stroke-opacity: var(--breakpoint-inactive-opacity);
+}
+
+.column-breakpoint.active svg {
+  fill: var(--breakpoint-fill);
+  stroke: var(--breakpoint-stroke);
+  fill-opacity: 1;
+  stroke-opacity: 1;
+}
+
+.column-breakpoint.disabled svg {
+  fill-opacity: var(--breakpoint-disabled-opacity);
+  stroke-opacity: var(--breakpoint-disabled-opacity);
+}
+
+.column-breakpoint.has-log.disabled svg {
+  fill-opacity: 0.5;
+  stroke-opacity: 0.5;
+}
+
+.column-breakpoint.disabled:not(.has-condition):not(.has-log) svg {
+  fill: var(--breakpoint-disabled-fill);
+  stroke: var(--breakpoint-disabled-stroke);
+}
+
+.column-breakpoint.has-condition svg {
+  fill: var(--breakpoint-condition-fill);
+  stroke: var(--breakpoint-condition-stroke);
+}
+
+.column-breakpoint.has-log svg {
+  fill: var(--logpoint-fill);
+  stroke: var(--logpoint-stroke);
+}
+
+.img.column-marker {
+  background-image: url(/images/column-marker.svg);
+}
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoint.js
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoint.js
@@ -29,24 +29,25 @@ type Props = {
 
 const breakpointImg = document.createElement("button");
 ReactDOM.render(<Svg name={"column-marker"} />, breakpointImg);
 
 function makeBookmark({ breakpoint }, { onClick, onContextMenu }) {
   const bp = breakpointImg.cloneNode(true);
 
   const isActive = breakpoint && !breakpoint.disabled;
+  const isDisabled = breakpoint && breakpoint.disabled;
   const condition = breakpoint && breakpoint.options.condition;
   const logValue = breakpoint && breakpoint.options.logValue;
 
   bp.className = classnames("column-breakpoint", {
     "has-condition": condition,
     "has-log": logValue,
     active: isActive,
-    disabled: !isActive
+    disabled: isDisabled
   });
 
   if (condition) {
     bp.setAttribute("title", condition);
   }
   bp.onclick = onClick;
 
   // NOTE: flow does not know about oncontextmenu
deleted file mode 100644
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
-
-.column-breakpoint {
-  display: inline;
-  padding-inline-start: 1px;
-  padding-inline-end: 3px;
-}
-
-.column-breakpoint:hover {
-  background-color: transparent;
-}
-
-.column-breakpoint svg {
-  display: inline-block;
-  cursor: pointer;
-  height: 13px;
-  width: 11px;
-  vertical-align: top;
-  fill: var(--blue-40);
-  stroke: var(--blue-60);
-}
-
-.column-breakpoint.disabled svg {
-  fill-opacity: 0.7;
-  stroke-opacity: 0.7;
-}
-
-.column-breakpoint.has-condition svg {
-  fill: var(--theme-graphs-yellow);
-  stroke: var(--theme-graphs-orange);
-}
-
-.column-breakpoint.has-log svg {
-  fill: var(--theme-graphs-purple);
-  stroke: var(--purple-60);
-}
-
-.theme-dark .column-breakpoint.active svg {
-  fill: var(--blue-55);
-  stroke: var(--blue-40);
-}
-
-.theme-dark .column-breakpoint.disabled svg {
-  fill: var(--blue-50);
-  stroke: var(--blue-60);
-  fill-opacity: 0.5;
-}
-
-.img.column-marker {
-  background-image: url(/images/column-marker.svg);
-}
--- a/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
+++ b/devtools/client/debugger/new/src/components/Editor/ColumnBreakpoints.js
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import React, { Component } from "react";
 
 import ColumnBreakpoint from "./ColumnBreakpoint";
-import "./ColumnBreakpoints.css";
 
 import { getSelectedSource, visibleColumnBreakpoints } from "../../selectors";
 import { connect } from "../../utils/connect";
 import { makeBreakpointId } from "../../utils/breakpoint";
 import { breakpointItemActions } from "./menus/breakpoints";
 import type { BreakpointItemActions } from "./menus/breakpoints";
 
 import type { Source } from "../../types";
--- a/devtools/client/debugger/new/src/components/Editor/Editor.css
+++ b/devtools/client/debugger/new/src/components/Editor/Editor.css
@@ -49,64 +49,24 @@
   top: var(--editor-header-height);
   left: 0px;
 }
 
 html[dir="rtl"] .editor-mount {
   direction: ltr;
 }
 
-.theme-light {
-  --gutter-hover-background-color: #dde1e4;
-  --breakpoint-fill: var(--blue-50);
-  --breakpoint-stroke: var(--blue-60);
-}
-
-.theme-dark {
-  --gutter-hover-background-color: #414141;
-  --breakpoint-fill: var(--blue-55);
-  --breakpoint-stroke: var(--blue-40);
-}
-
 .theme-light .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-40);
 }
 
 .theme-dark .cm-s-mozilla .empty-line .CodeMirror-linenumber {
   color: var(--grey-50);
 }
 
-.new-breakpoint .CodeMirror-linenumber {
-  pointer-events: none;
-}
-
-:not(.empty-line):not(.new-breakpoint)
-  > .CodeMirror-gutter-wrapper:hover
-  > .CodeMirror-linenumber::after {
-  content: "";
-  position: absolute;
-  /* paint below the number */
-  z-index: -1;
-  top: 0;
-  left: 0;
-  right: -7px;
-  bottom: 0;
-  height: 15px;
-  background-color: var(--gutter-hover-background-color);
-  mask: url(/images/breakpoint.svg) no-repeat;
-  mask-size: auto 15px;
-  mask-position: right;
-}
-
-.editor-wrapper .breakpoints {
-  position: absolute;
-  top: 0;
-  left: 0;
-}
-
 .function-search {
   max-height: 300px;
   overflow: hidden;
 }
 
 .function-search .results {
   height: auto;
 }
@@ -114,60 +74,16 @@ html[dir="rtl"] .editor-mount {
 .editor.hit-marker {
   height: 15px;
 }
 
 .editor-wrapper .highlight-lines {
   background: var(--theme-selection-background-hover);
 }
 
-.editor.new-breakpoint svg {
-  fill: var(--breakpoint-fill);
-  stroke: var(--breakpoint-stroke);
-  width: 60px;
-  height: 15px;
-  position: absolute;
-  top: 0px;
-  right: -4px;
-}
-
-.inline-bp {
-  background-color: #9ddfff;
-  width: 20px;
-  padding: 0px 5px;
-  margin: 0px 4px;
-  border-radius: 5px;
-  border-color: blue;
-  border: 1px solid #00b6ff;
-}
-
-.editor .breakpoint {
-  position: absolute;
-  right: -2px;
-}
-
-.editor.new-breakpoint.folding-enabled svg {
-  right: -16px;
-}
-
-.new-breakpoint.has-condition .CodeMirror-gutter-wrapper svg {
-  fill: var(--theme-graphs-yellow);
-  stroke: var(--theme-graphs-orange);
-}
-
-.new-breakpoint.has-log .CodeMirror-gutter-wrapper svg {
-  fill: var(--theme-graphs-purple);
-  stroke: var(--purple-60);
-}
-
-.editor.new-breakpoint.breakpoint-disabled svg {
-  fill-opacity: 0.7;
-  stroke-opacity: 0.7;
-}
-
 .CodeMirror {
   width: 100%;
   height: 100%;
 }
 
 .editor-wrapper .editor-mount {
   width: 100%;
   background-color: var(--theme-body-background);
@@ -193,17 +109,17 @@ html[dir="rtl"] .editor-mount {
   z-index: 0;
 }
 
 .theme-dark .editor-wrapper .CodeMirror-line .cm-comment {
   color: var(--theme-comment);
 }
 
 .debug-expression,
-.new-debug-line .column-breakpoint {
+.debug-expression ~ .CodeMirror-widget {
   background-color: var(--debug-expression-background);
 }
 
 debug-expression-error {
   background-color: var(--debug-expression-error-background);
 }
 
 .new-debug-line .CodeMirror-line {
--- a/devtools/client/debugger/new/src/components/Editor/index.js
+++ b/devtools/client/debugger/new/src/components/Editor/index.js
@@ -72,16 +72,17 @@ import {
   onMouseOver,
   startOperation,
   endOperation
 } from "../../utils/editor";
 
 import { resizeToggleButton, resizeBreakpointGutter } from "../../utils/ui";
 
 import "./Editor.css";
+import "./Breakpoints.css";
 import "./Highlight.css";
 
 import type SourceEditor from "../../utils/editor/source-editor";
 import type { SymbolDeclarations } from "../../workers/parser";
 import type { SourceLocation, Source } from "../../types";
 
 const cssVars = {
   searchbarHeight: "var(--editor-searchbar-height)",
@@ -215,17 +216,21 @@ class Editor extends PureComponent<Props
 
     const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
     const searchAgainPrevKey = L10N.getStr(
       "sourceSearch.search.againPrev.key2"
     );
 
     shortcuts.on(L10N.getStr("toggleBreakpoint.key"), this.onToggleBreakpoint);
     shortcuts.on(
-      L10N.getStr("toggleCondPanel.key"),
+      L10N.getStr("toggleCondPanel.breakpoint.key"),
+      this.onToggleConditionalPanel
+    );
+    shortcuts.on(
+      L10N.getStr("toggleCondPanel.logPoint.key"),
       this.onToggleConditionalPanel
     );
     shortcuts.on(L10N.getStr("sourceTabs.closeTab.key"), this.onClosePress);
     shortcuts.on("Esc", this.onEscape);
     shortcuts.on(searchAgainPrevKey, this.onSearchAgain);
     shortcuts.on(searchAgainKey, this.onSearchAgain);
   }
 
@@ -247,17 +252,18 @@ class Editor extends PureComponent<Props
 
     const searchAgainKey = L10N.getStr("sourceSearch.search.again.key2");
     const searchAgainPrevKey = L10N.getStr(
       "sourceSearch.search.againPrev.key2"
     );
     const shortcuts = this.context.shortcuts;
     shortcuts.off(L10N.getStr("sourceTabs.closeTab.key"));
     shortcuts.off(L10N.getStr("toggleBreakpoint.key"));
-    shortcuts.off(L10N.getStr("toggleCondPanel.key"));
+    shortcuts.off(L10N.getStr("toggleCondPanel.breakpoint.key"));
+    shortcuts.off(L10N.getStr("toggleCondPanel.logPoint.key"));
     shortcuts.off(searchAgainPrevKey);
     shortcuts.off(searchAgainKey);
   }
 
   componentDidUpdate(prevProps, prevState) {
     const { selectedSource } = this.props;
     // NOTE: when devtools are opened, the editor is not set when
     // the source loads so we need to wait until the editor is
@@ -299,21 +305,23 @@ class Editor extends PureComponent<Props
 
     this.props.toggleBreakpointAtLine(line);
   };
 
   onToggleConditionalPanel = (key, e: KeyboardEvent) => {
     e.stopPropagation();
     e.preventDefault();
     const line = this.getCurrentLine();
+
     if (typeof line !== "number") {
       return;
     }
 
-    this.toggleConditionalPanel(line);
+    const isLog = key === L10N.getStr("toggleCondPanel.logPoint.key");
+    this.toggleConditionalPanel(line, isLog);
   };
 
   onEditorScroll = throttle(this.props.updateViewport, 100);
 
   onKeyDown(e: KeyboardEvent) {
     const { codeMirror } = this.state.editor;
     const { key, target } = e;
     const codeWrapper = codeMirror.getWrapperElement();
@@ -452,37 +460,40 @@ class Editor extends PureComponent<Props
         this.state.editor,
         selectedSource,
         e
       );
       jumpToMappedLocation(sourceLocation);
     }
   }
 
-  toggleConditionalPanel = line => {
+  toggleConditionalPanel = (line, log: boolean = false) => {
     const {
       conditionalPanelLocation,
       closeConditionalPanel,
       openConditionalPanel,
       selectedSource
     } = this.props;
 
     if (conditionalPanelLocation) {
       return closeConditionalPanel();
     }
 
     if (!selectedSource) {
       return;
     }
 
-    return openConditionalPanel({
-      line: line,
-      sourceId: selectedSource.id,
-      sourceUrl: selectedSource.url
-    });
+    return openConditionalPanel(
+      {
+        line: line,
+        sourceId: selectedSource.id,
+        sourceUrl: selectedSource.url
+      },
+      log
+    );
   };
 
   shouldScrollToLocation(nextProps) {
     const { selectedLocation, selectedSource } = this.props;
     const { editor } = this.state;
 
     if (
       !editor ||
--- a/devtools/client/debugger/new/src/components/Editor/menus/breakpoints.js
+++ b/devtools/client/debugger/new/src/components/Editor/menus/breakpoints.js
@@ -34,29 +34,29 @@ export const removeBreakpointItem = (
 });
 
 export const addConditionalBreakpointItem = (
   location: SourceLocation,
   breakpointActions: BreakpointItemActions
 ) => ({
   id: "node-menu-add-conditional-breakpoint",
   label: L10N.getStr("editor.addConditionBreakpoint"),
-  accelerator: L10N.getStr("toggleCondPanel.key"),
+  accelerator: L10N.getStr("toggleCondPanel.breakpoint.key"),
   accesskey: L10N.getStr("editor.addConditionBreakpoint.accesskey"),
   disabled: false,
   click: () => breakpointActions.openConditionalPanel(location)
 });
 
 export const editConditionalBreakpointItem = (
   location: SourceLocation,
   breakpointActions: BreakpointItemActions
 ) => ({
   id: "node-menu-edit-conditional-breakpoint",
   label: L10N.getStr("editor.editConditionBreakpoint"),
-  accelerator: L10N.getStr("toggleCondPanel.key"),
+  accelerator: L10N.getStr("toggleCondPanel.breakpoint.key"),
   accesskey: L10N.getStr("editor.addConditionBreakpoint.accesskey"),
   disabled: false,
   click: () => breakpointActions.openConditionalPanel(location)
 });
 
 export const conditionalBreakpointItem = (
   breakpoint: Breakpoint,
   breakpointActions: BreakpointItemActions
@@ -74,29 +74,29 @@ export const addLogPointItem = (
   location: SourceLocation,
   breakpointActions: BreakpointItemActions
 ) => ({
   id: "node-menu-add-log-point",
   label: L10N.getStr("editor.addLogPoint"),
   accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
   disabled: false,
   click: () => breakpointActions.openConditionalPanel(location, true),
-  accelerator: L10N.getStr("toggleCondPanel.key")
+  accelerator: L10N.getStr("toggleCondPanel.logPoint.key")
 });
 
 export const editLogPointItem = (
   location: SourceLocation,
   breakpointActions: BreakpointItemActions
 ) => ({
   id: "node-menu-edit-log-point",
   label: L10N.getStr("editor.editLogPoint"),
   accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
   disabled: false,
   click: () => breakpointActions.openConditionalPanel(location, true),
-  accelerator: L10N.getStr("toggleCondPanel.key")
+  accelerator: L10N.getStr("toggleCondPanel.logPoint.key")
 });
 
 export const logPointItem = (
   breakpoint: Breakpoint,
   breakpointActions: BreakpointItemActions
 ) => {
   const {
     options: { logValue },
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/SourcesTree.js
@@ -329,19 +329,23 @@ class SourcesTree extends Component<Prop
     const { worker } = this.props;
 
     if (!features.windowlessWorkers && worker) {
       return null;
     }
 
     return this.renderPane(
       this.renderThreadHeader(),
-      <div key="tree" className="sources-list">
-        {this.renderTree()}
-      </div>
+      this.isEmpty() ? (
+        this.renderEmptyElement(L10N.getStr("noSourcesText"))
+      ) : (
+        <div key="tree" className="sources-list">
+          {this.renderTree()}
+        </div>
+      )
     );
   }
 }
 
 function getSourceForTree(
   state: AppState,
   displayedSources: SourcesMap,
   source: ?Source,
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTree.spec.js
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/SourcesTree.spec.js
@@ -23,16 +23,24 @@ describe("SourcesTree", () => {
     showMenu.mockClear();
   });
 
   it("Should show the tree with nothing expanded", async () => {
     const { component } = render();
     expect(component).toMatchSnapshot();
   });
 
+  it("Should show a 'No Sources' message if there are no sources", async () => {
+    const { component, defaultState } = render();
+    const sourceTree = defaultState.sourceTree;
+    sourceTree.contents = [];
+    component.setState({ sourceTree: sourceTree });
+    expect(component).toMatchSnapshot();
+  });
+
   describe("When loading initial source", () => {
     it("Shows the tree with one.js, two.js and three.js expanded", async () => {
       const { component, props } = render();
       await component.setProps({
         ...props,
         expanded: ["one.js", "two.js", "three.js"]
       });
 
--- a/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTree.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/PrimaryPanes/tests/__snapshots__/SourcesTree.spec.js.snap
@@ -43,16 +43,42 @@ exports[`SourcesTree After changing expa
       onFocus={[Function]}
       preventBlur={true}
       renderItem={[Function]}
     />
   </div>
 </div>
 `;
 
+exports[`SourcesTree Should show a 'No Sources' message if there are no sources 1`] = `
+<div
+  className="sources-pane thread"
+  key="pane"
+>
+  <div
+    className="node thread-header"
+  >
+    <AccessibleImage
+      className="file"
+    />
+    <span
+      className="label"
+    >
+      Main Thread
+    </span>
+  </div>
+  <div
+    className="no-sources-message"
+    key="empty"
+  >
+    This page has no sources.
+  </div>
+</div>
+`;
+
 exports[`SourcesTree Should show the tree with nothing expanded 1`] = `
 <div
   className="sources-pane thread"
   key="pane"
 >
   <div
     className="node thread-header"
   >
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/BreakpointsContextMenu.js
@@ -200,45 +200,47 @@ export default function showContextMenu(
 
   const addConditionItem = {
     id: "node-menu-add-condition",
     label: addConditionLabel,
     accesskey: addConditionKey,
     click: () => {
       selectSpecificLocation(selectedLocation);
       openConditionalPanel(selectedLocation);
-    }
+    },
+    accelerator: L10N.getStr("toggleCondPanel.breakpoint.key")
   };
 
   const editConditionItem = {
     id: "node-menu-edit-condition",
     label: editConditionLabel,
     accesskey: editConditionKey,
     click: () => {
       selectSpecificLocation(selectedLocation);
       openConditionalPanel(selectedLocation);
-    }
+    },
+    accelerator: L10N.getStr("toggleCondPanel.breakpoint.key")
   };
 
   const addLogPointItem = {
     id: "node-menu-add-log-point",
     label: L10N.getStr("editor.addLogPoint"),
     accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
     disabled: false,
     click: () => openConditionalPanel(selectedLocation, true),
-    accelerator: L10N.getStr("toggleCondPanel.key")
+    accelerator: L10N.getStr("toggleCondPanel.logPoint.key")
   };
 
   const editLogPointItem = {
     id: "node-menu-edit-log-point",
     label: L10N.getStr("editor.editLogPoint"),
     accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
     disabled: false,
     click: () => openConditionalPanel(selectedLocation, true),
-    accelerator: L10N.getStr("toggleCondPanel.key")
+    accelerator: L10N.getStr("toggleCondPanel.logPoint.key")
   };
 
   const removeLogPointItem = {
     id: "node-menu-remove-log",
     label: L10N.getStr("editor.removeLogPoint.label"),
     accesskey: L10N.getStr("editor.removeLogPoint.accesskey"),
     disabled: false,
     click: () =>
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.css
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.css
@@ -1,46 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
-.scopes-content .toggle-map-scopes {
-  border-bottom: 1px solid var(--theme-splitter-color);
-  margin-bottom: 3px;
-  margin-left: 10px;
-  padding: 0.5em 0;
-}
+ .secondary-panes .map-scopes-header {
+  padding-inline-end: 3px;
+ }
 
-.scopes-content .toggle-map-scopes input {
-  padding-inline-start: 2px;
-  margin-inline-start: 0;
-  vertical-align: text-bottom;
-}
-
-.scopes-content .toggle-map-scopes-label {
-  padding-inline-start: 2px;
-  padding-inline-end: 8px;
-  cursor: default;
-  flex-grow: 1;
-  -moz-user-select: none;
+.secondary-panes .header-buttons .img.shortcuts {
+  width: 14px;
+  height: 14px;
+  /* Better vertical centering of the icon */
+  margin-top: -2px;
 }
 
 .scopes-content .toggle-map-scopes a.mdn {
-  padding-inline-end: 10px;
+  padding-inline-start: 3px;
 }
 
 .scopes-content .toggle-map-scopes .img.shortcuts {
   background: var(--theme-comment);
 }
 
-.scopes-content .toggle-map-scopes {
-  display: flex;
-  align-items: center;
-}
-
 .object-node.default-property {
   opacity: 0.6;
 }
 
 .object-node {
   padding-left: 4px;
 }
 
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/Scopes.js
@@ -1,43 +1,37 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 import React, { PureComponent } from "react";
-import { isGeneratedId } from "devtools-source-map";
 import { connect } from "../../utils/connect";
-import { features } from "../../utils/prefs";
 import actions from "../../actions";
 import { createObjectClient } from "../../client/firefox";
 
 import {
   getSelectedSource,
   getSelectedFrame,
   getGeneratedFrameScope,
   getOriginalFrameScope,
   getIsPaused,
   getPauseReason,
   getMapScopes,
   getCurrentThread
 } from "../../selectors";
 import { getScopes } from "../../utils/pause/scopes";
 
 import { objectInspector } from "devtools-reps";
-import AccessibleImage from "../shared/AccessibleImage";
 
 import type { Why } from "../../types";
 import type { NamedValue } from "../../utils/pause/scopes/types";
 
 import "./Scopes.css";
 
-const mdnLink =
-  "https://developer.mozilla.org/en-US/docs/Tools/Debugger/Using_the_Debugger_map_scopes_feature";
-
 const { ObjectInspector } = objectInspector;
 
 type Props = {
   isPaused: boolean,
   selectedFrame: Object,
   generatedFrameScopes: Object,
   originalFrameScopes: Object | null,
   isLoading: boolean,
@@ -106,44 +100,16 @@ class Scopes extends PureComponent<Props
       });
     }
   }
 
   onToggleMapScopes = () => {
     this.props.toggleMapScopes();
   };
 
-  renderMapScopes() {
-    const { selectedFrame, shouldMapScopes } = this.props;
-
-    if (
-      !features.mapScopes ||
-      !selectedFrame ||
-      isGeneratedId(selectedFrame.location.sourceId)
-    ) {
-      return null;
-    }
-
-    return (
-      <div className="toggle-map-scopes" onClick={this.onToggleMapScopes}>
-        <input
-          type="checkbox"
-          checked={shouldMapScopes ? "checked" : ""}
-          onChange={e => e.stopPropagation() && this.onToggleMapScopes()}
-        />
-        <div className="toggle-map-scopes-label">
-          <span>{L10N.getStr("scopes.mapScopes")}</span>
-        </div>
-        <a className="mdn" target="_blank" href={mdnLink}>
-          <AccessibleImage className="shortcuts" />
-        </a>
-      </div>
-    );
-  }
-
   renderScopesList() {
     const {
       isPaused,
       isLoading,
       openLink,
       openElementInInspector,
       shouldMapScopes
     } = this.props;
@@ -161,30 +127,16 @@ class Scopes extends PureComponent<Props
             autoExpandDepth={1}
             disableWrap={true}
             dimTopLevelWindow={true}
             openLink={openLink}
             createObjectClient={grip => createObjectClient(grip)}
             onDOMNodeClick={grip => openElementInInspector(grip)}
             onInspectIconClick={grip => openElementInInspector(grip)}
           />
-          {originalScopes && shouldMapScopes ? (
-            <div className="scope-type-toggle">
-              <button
-                onClick={e => {
-                  e.preventDefault();
-                  this.setState({ showOriginal: !showOriginal });
-                }}
-              >
-                {showOriginal
-                  ? L10N.getStr("scopes.toggleToGenerated")
-                  : L10N.getStr("scopes.toggleToOriginal")}
-              </button>
-            </div>
-          ) : null}
         </div>
       );
     }
 
     let stateText = L10N.getStr("scopes.notPaused");
     if (isPaused) {
       if (isLoading) {
         stateText = L10N.getStr("loadingText");
@@ -196,22 +148,17 @@ class Scopes extends PureComponent<Props
     return (
       <div className="pane scopes-list">
         <div className="pane-info">{stateText}</div>
       </div>
     );
   }
 
   render() {
-    return (
-      <div className="scopes-content">
-        {this.renderMapScopes()}
-        {this.renderScopesList()}
-      </div>
-    );
+    return <div className="scopes-content">{this.renderScopesList()}</div>;
   }
 }
 
 const mapStateToProps = state => {
   const thread = getCurrentThread(state);
   const selectedFrame = getSelectedFrame(state, thread);
   const selectedSource = getSelectedSource(state);
 
--- a/devtools/client/debugger/new/src/components/SecondaryPanes/index.js
+++ b/devtools/client/debugger/new/src/components/SecondaryPanes/index.js
@@ -1,26 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import React, { Component } from "react";
+import { isGeneratedId } from "devtools-source-map";
 import { connect } from "../../utils/connect";
 import { List } from "immutable";
 
 import actions from "../../actions";
 import {
   getTopFrame,
   getBreakpointsList,
   getBreakpointsDisabled,
   getBreakpointsLoading,
   getExpressions,
   getIsWaitingOnBreak,
+  getMapScopes,
+  getSelectedFrame,
   getShouldPauseOnExceptions,
   getShouldPauseOnCaughtExceptions,
   getWorkers,
   getCurrentThread
 } from "../../selectors";
 
 import AccessibleImage from "../shared/AccessibleImage";
 import { prefs, features } from "../../utils/prefs";
@@ -35,17 +38,17 @@ import CommandBar from "./CommandBar";
 import UtilsBar from "./UtilsBar";
 import XHRBreakpoints from "./XHRBreakpoints";
 import EventListeners from "./EventListeners";
 
 import Scopes from "./Scopes";
 
 import "./SecondaryPanes.css";
 
-import type { Expression, WorkerList } from "../../types";
+import type { Expression, Frame, WorkerList } from "../../types";
 
 type AccordionPaneItem = {
   header: string,
   component: any,
   opened?: boolean,
   onToggle?: () => void,
   shouldOpen?: () => boolean,
   buttons?: any
@@ -69,29 +72,35 @@ type State = {
   showXHRInput: boolean
 };
 
 type Props = {
   expressions: List<Expression>,
   hasFrames: boolean,
   horizontal: boolean,
   breakpoints: Object,
+  selectedFrame: ?Frame,
   breakpointsDisabled: boolean,
   breakpointsLoading: boolean,
   isWaitingOnBreak: boolean,
+  shouldMapScopes: boolean,
   shouldPauseOnExceptions: boolean,
   shouldPauseOnCaughtExceptions: boolean,
   workers: WorkerList,
   toggleShortcutsModal: () => void,
   toggleAllBreakpoints: typeof actions.toggleAllBreakpoints,
+  toggleMapScopes: typeof actions.toggleMapScopes,
   evaluateExpressions: typeof actions.evaluateExpressions,
   pauseOnExceptions: typeof actions.pauseOnExceptions,
   breakOnNext: typeof actions.breakOnNext
 };
 
+const mdnLink =
+  "https://developer.mozilla.org/docs/Tools/Debugger/Using_the_Debugger_map_scopes_feature?utm_source=devtools&utm_medium=debugger-map-scopes";
+
 class SecondaryPanes extends Component<Props, State> {
   constructor(props: Props) {
     super(props);
 
     this.state = {
       showExpressionsInput: false,
       showXHRInput: false
     };
@@ -203,22 +212,61 @@ class SecondaryPanes extends Component<P
   }
 
   getScopeItem(): AccordionPaneItem {
     return {
       header: L10N.getStr("scopes.header"),
       className: "scopes-pane",
       component: <Scopes />,
       opened: prefs.scopesVisible,
+      buttons: this.getScopesButtons(),
       onToggle: opened => {
         prefs.scopesVisible = opened;
       }
     };
   }
 
+  getScopesButtons() {
+    const { selectedFrame, shouldMapScopes } = this.props;
+
+    if (
+      !features.mapScopes ||
+      !selectedFrame ||
+      isGeneratedId(selectedFrame.location.sourceId)
+    ) {
+      return null;
+    }
+
+    return [
+      <div>
+        <label
+          className="map-scopes-header"
+          title={L10N.getStr("scopes.mapping.label")}
+          onClick={e => e.stopPropagation()}
+        >
+          <input
+            type="checkbox"
+            checked={shouldMapScopes ? "checked" : ""}
+            onChange={e => this.props.toggleMapScopes()}
+          />
+          {L10N.getStr("scopes.map.label")}
+        </label>
+        <a
+          className="mdn"
+          target="_blank"
+          href={mdnLink}
+          onClick={e => e.stopPropagation()}
+          title={L10N.getStr("scopes.helpTooltip.label")}
+        >
+          <AccessibleImage className="shortcuts" />
+        </a>
+      </div>
+    ];
+  }
+
   getWatchItem(): AccordionPaneItem {
     return {
       header: L10N.getStr("watchExpressions.header"),
       className: "watch-expressions-pane",
       buttons: this.watchExpressionHeaderButtons(),
       component: (
         <Expressions
           showInput={this.state.showExpressionsInput}
@@ -410,30 +458,34 @@ class SecondaryPanes extends Component<P
         {this.renderUtilsBar()}
       </div>
     );
   }
 }
 
 const mapStateToProps = state => {
   const thread = getCurrentThread(state);
+
   return {
     expressions: getExpressions(state),
     hasFrames: !!getTopFrame(state, thread),
     breakpoints: getBreakpointsList(state),
     breakpointsDisabled: getBreakpointsDisabled(state),
     breakpointsLoading: getBreakpointsLoading(state),
     isWaitingOnBreak: getIsWaitingOnBreak(state, thread),
+    selectedFrame: getSelectedFrame(state, thread),
+    shouldMapScopes: getMapScopes(state),
     shouldPauseOnExceptions: getShouldPauseOnExceptions(state),
     shouldPauseOnCaughtExceptions: getShouldPauseOnCaughtExceptions(state),
     workers: getWorkers(state)
   };
 };
 
 export default connect(
   mapStateToProps,
   {
     toggleAllBreakpoints: actions.toggleAllBreakpoints,
     evaluateExpressions: actions.evaluateExpressions,
     pauseOnExceptions: actions.pauseOnExceptions,
+    toggleMapScopes: actions.toggleMapScopes,
     breakOnNext: actions.breakOnNext
   }
 )(SecondaryPanes);
--- a/devtools/client/debugger/new/src/components/ShortcutsModal.js
+++ b/devtools/client/debugger/new/src/components/ShortcutsModal.js
@@ -41,18 +41,22 @@ export class ShortcutsModal extends Comp
   renderEditorShortcuts() {
     return (
       <ul className="shortcuts-list">
         {this.renderShorcutItem(
           L10N.getStr("shortcuts.toggleBreakpoint"),
           formatKeyShortcut(L10N.getStr("toggleBreakpoint.key"))
         )}
         {this.renderShorcutItem(
-          L10N.getStr("shortcuts.toggleCondPanel"),
-          formatKeyShortcut(L10N.getStr("toggleCondPanel.key"))
+          L10N.getStr("shortcuts.toggleCondPanel.breakpoint"),
+          formatKeyShortcut(L10N.getStr("toggleCondPanel.breakpoint.key"))
+        )}
+        {this.renderShorcutItem(
+          L10N.getStr("shortcuts.toggleCondPanel.logPoint"),
+          formatKeyShortcut(L10N.getStr("toggleCondPanel.logPoint.key"))
         )}
       </ul>
     );
   }
 
   renderSteppingShortcuts() {
     return (
       <ul className="shortcuts-list">
--- a/devtools/client/debugger/new/src/components/test/__snapshots__/ShortcutsModal.spec.js.snap
+++ b/devtools/client/debugger/new/src/components/test/__snapshots__/ShortcutsModal.spec.js.snap
@@ -28,27 +28,40 @@ exports[`ShortcutsModal renders when ena
               key="Ctrl+B"
             >
               Ctrl+B
             </span>
           </span>
         </li>
         <li>
           <span>
-            Toggle Conditional Panel
+            Edit Conditional Breakpoint
           </span>
           <span>
             <span
               className="keystroke"
               key="Ctrl+Shift+B"
             >
               Ctrl+Shift+B
             </span>
           </span>
         </li>
+        <li>
+          <span>
+            Edit Log Point
+          </span>
+          <span>
+            <span
+              className="keystroke"
+              key="Ctrl+Shift+Y"
+            >
+              Ctrl+Shift+Y
+            </span>
+          </span>
+        </li>
       </ul>
     </div>
     <div
       className="shortcuts-section"
     >
       <h2>
         Stepping
       </h2>
--- a/devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.js
+++ b/devtools/client/debugger/new/src/selectors/visibleColumnBreakpoints.js
@@ -43,18 +43,19 @@ function contains(location: PartialPosit
         location.column <= range.end.column))
   );
 }
 
 function groupBreakpoints(breakpoints, selectedSource) {
   if (!breakpoints) {
     return {};
   }
+
   const map: any = groupBy(
-    breakpoints,
+    breakpoints.filter(breakpoint => !breakpoint.options.hidden),
     breakpoint => getSelectedLocation(breakpoint, selectedSource).line
   );
 
   for (const line in map) {
     map[line] = groupBy(
       map[line],
       breakpoint => getSelectedLocation(breakpoint, selectedSource).column
     );
--- a/devtools/client/locales/en-US/debugger.properties
+++ b/devtools/client/locales/en-US/debugger.properties
@@ -238,21 +238,27 @@ allShortcut.key=CmdOrCtrl+/
 functionSearch.key=CmdOrCtrl+Shift+O
 
 # LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle
 # breakpoints.
 # Do not localize "CmdOrCtrl+B", or change the format of the string. These are
 # key identifiers, not messages displayed to the user.
 toggleBreakpoint.key=CmdOrCtrl+B
 
-# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle
-# the conditional breakpoint panel.
+# LOCALIZATION NOTE (toggleCondPanel.breakpoint.key): A key shortcut to toggle
+# the conditional panel for breakpoints.
 # Do not localize "CmdOrCtrl+Shift+B", or change the format of the string. These are
 # key identifiers, not messages displayed to the user.
-toggleCondPanel.key=CmdOrCtrl+Shift+B
+toggleCondPanel.breakpoint.key=CmdOrCtrl+Shift+B
+
+# LOCALIZATION NOTE (toggleCondPanel.logPoint.key): A key shortcut to toggle
+# the conditional panel for log points.
+# Do not localize "CmdOrCtrl+Shift+Y", or change the format of the string. These are
+# key identifiers, not messages displayed to the user.
+toggleCondPanel.logPoint.key=CmdOrCtrl+Shift+Y
 
 # LOCALIZATION NOTE (stepOut.key): A key shortcut to
 # step out.
 stepOut.key=Shift+F11
 
 # LOCALIZATION NOTE (shortcuts.header.editor): Sections header in
 # the shortcuts modal for keyboard shortcuts related to editing.
 shortcuts.header.editor=Editor
@@ -686,23 +692,26 @@ scopes.header=Scopes
 # LOCALIZATION NOTE (scopes.notAvailable): Scopes right sidebar pane message
 # for when the debugger is paused, but there isn't pause data.
 scopes.notAvailable=Scopes unavailable
 
 # LOCALIZATION NOTE (scopes.notPaused): Scopes right sidebar pane message
 # for when the debugger is not paused.
 scopes.notPaused=Not paused
 
-# LOCALIZATION NOTE (scopes.toggleToGenerated): Link displayed in the right
-# sidebar scope pane to update the view to show generated scope data.
-scopes.toggleToGenerated=Show generated scope
+# LOCALIZATION NOTE (scopes.mapping.label): Scopes right sidebar pane
+# tooltip for checkbox and label
+scopes.mapping.label=Map original variable names
 
-# LOCALIZATION NOTE (scopes.toggleToOriginal): Link displayed in the right
-# sidebar scope pane to update the view to show original scope data.
-scopes.toggleToOriginal=Show original scope
+# LOCALIZATION NOTE (scopes.helpTooltip.label): Scopes right sidebar pane
+# icon tooltip for link to MDN
+scopes.helpTooltip.label=Learn more about map scopes
+
+# LOCALIZATION NOTE (scopes.map.label): Checkbox label to map scopes
+scopes.map.label=Map
 
 # LOCALIZATION NOTE (scopes.block): Refers to a block of code in
 # the scopes pane when the debugger is paused.
 scopes.block=Block
 
 # LOCALIZATION NOTE (sources.header): Sources left sidebar header
 sources.header=Sources
 
@@ -1020,19 +1029,23 @@ ctrl=Ctrl
 # anonymous.
 anonymousFunction=<anonymous>
 
 # LOCALIZATION NOTE (shortcuts.toggleBreakpoint): text describing
 # keyboard shortcut action for toggling breakpoint
 shortcuts.toggleBreakpoint=Toggle Breakpoint
 shortcuts.toggleBreakpoint.accesskey=B
 
-# LOCALIZATION NOTE (shortcuts.toggleCondPanel): text describing
-# keyboard shortcut action for toggling conditional panel keyboard
-shortcuts.toggleCondPanel=Toggle Conditional Panel
+# LOCALIZATION NOTE (shortcuts.toggleCondPanel.breakpoint): text describing
+# keyboard shortcut action for toggling conditional panel for breakpoints
+shortcuts.toggleCondPanel.breakpoint=Edit Conditional Breakpoint
+
+# LOCALIZATION NOTE (shortcuts.toggleCondPanel.logPoint): text describing
+# keyboard shortcut action for toggling conditional panel for log points
+shortcuts.toggleCondPanel.logPoint=Edit Log Point
 
 # LOCALIZATION NOTE (shortcuts.pauseOrResume): text describing
 # keyboard shortcut action for pause of resume
 shortcuts.pauseOrResume=Pause/Resume
 
 # LOCALIZATION NOTE (shortcuts.stepOver): text describing
 # keyboard shortcut action for stepping over
 shortcuts.stepOver=Step Over