Browse Source

Merge pull request #5 from jupyterlab/master

merge ui-iterration
KsavinN 5 years ago
parent
commit
f86e13fc07

+ 2 - 1
package.json

@@ -46,8 +46,9 @@
     "@jupyterlab/coreutils": "^3.1.0-alpha.1",
     "@jupyterlab/fileeditor": "^1.1.0-alpha.1",
     "@jupyterlab/launcher": "^1.1.0-alpha.1",
-    "@jupyterlab/services": "^4.1.0-alpha.1",
     "@jupyterlab/notebook": "^1.1.0-alpha.1",
+    "@jupyterlab/services": "^4.1.0-alpha.1",
+    "@phosphor/algorithm": "^1.2.0",
     "@phosphor/coreutils": "^1.3.1",
     "@phosphor/disposable": "^1.2.0",
     "@phosphor/widgets": "^1.8.0",

+ 4 - 0
src/breakpoints/index.ts

@@ -0,0 +1,4 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export * from './widget';

+ 43 - 0
src/breakpoints/widget.ts

@@ -0,0 +1,43 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { Toolbar, ToolbarButton } from '@jupyterlab/apputils';
+
+import { Widget, Panel } from '@phosphor/widgets';
+
+export class BreakPointsWidget extends Panel {
+  readonly body: Panel;
+
+  readonly header: Panel;
+
+  readonly label: Widget;
+
+  readonly toolbar: Toolbar;
+
+  constructor() {
+    super();
+
+    this.header = new Panel();
+    this.header.addClass('jp-DebuggerSidebarVariables-header');
+    this.addWidget(this.header);
+
+    this.label = new Widget();
+    this.label.node.textContent = 'BreakPoints';
+    this.label.addClass('jp-DebuggerSidebarVariables-header-label');
+    this.header.addWidget(this.label);
+
+    const toolbar = new Toolbar();
+    toolbar.addItem(
+      'deactivate',
+      new ToolbarButton({
+        iconClassName: 'jp-DebuggerDeactivateIcon',
+        onClick: () => {
+          console.log('`deactivate` was clicked');
+        },
+        tooltip: 'Deactivate Breakpoints'
+      })
+    );
+    this.toolbar = toolbar;
+    this.header.addWidget(this.toolbar);
+  }
+}

+ 4 - 0
src/callstack/index.ts

@@ -0,0 +1,4 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export * from './widget';

+ 55 - 0
src/callstack/widget.ts

@@ -0,0 +1,55 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { Toolbar, ToolbarButton } from '@jupyterlab/apputils';
+
+import { Widget, Panel } from '@phosphor/widgets';
+
+export class CallstackWidget extends Panel {
+  readonly header: Panel;
+
+  readonly label: Widget;
+
+  readonly toolbar: Toolbar;
+
+  constructor() {
+    super();
+
+    this.header = new Panel();
+    this.header.addClass('jp-DebuggerSidebarVariables-header');
+    this.addWidget(this.header);
+
+    this.label = new Widget();
+    this.label.node.textContent = 'Call stack';
+    this.label.addClass('jp-DebuggerSidebarVariables-header-label');
+    this.header.addWidget(this.label);
+
+    const toolbar = new Toolbar();
+    toolbar.addItem(
+      'continue',
+      new ToolbarButton({
+        iconClassName: 'jp-RunIcon',
+        onClick: () => {
+          console.log('`run` was clicked');
+        },
+        tooltip: 'Continue'
+      })
+    );
+    toolbar.addItem(
+      'stop',
+      new ToolbarButton({
+        iconClassName: 'jp-StopIcon',
+        onClick: () => {
+          console.log('`stop` was clicked');
+        },
+        tooltip: 'Stop'
+      })
+    );
+    toolbar.addItem('step-over', new ToolbarButton({ label: 'Step Over' }));
+    toolbar.addItem('step-in', new ToolbarButton({ label: 'Step In' }));
+    toolbar.addItem('step-out', new ToolbarButton({ label: 'Step Out' }));
+
+    this.toolbar = toolbar;
+    this.header.addWidget(this.toolbar);
+  }
+}

+ 6 - 6
src/debugger.ts

@@ -12,6 +12,12 @@ import { IDisposable } from '@phosphor/disposable';
 import { DebuggerSidebar } from './sidebar';
 
 export class Debugger extends BoxPanel {
+  readonly model: Debugger.Model;
+
+  readonly tabs = new TabPanel();
+
+  readonly sidebar: DebuggerSidebar;
+
   constructor(options: Debugger.IOptions) {
     super({ direction: 'left-to-right' });
 
@@ -24,12 +30,6 @@ export class Debugger extends BoxPanel {
     this.addWidget(this.sidebar);
   }
 
-  readonly model: Debugger.Model;
-
-  readonly tabs = new TabPanel();
-
-  readonly sidebar: DebuggerSidebar;
-
   dispose(): void {
     if (this.isDisposed) {
       return;

+ 2 - 1
src/index.ts

@@ -191,4 +191,5 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
   sidebar,
   tracker
 ];
-export default plugins;
+const plugin: JupyterFrontEndPlugin<any> = plugins[3];
+export default plugin;

+ 23 - 2
src/sidebar.ts

@@ -1,17 +1,38 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
-import { Widget } from '@phosphor/widgets';
+import { SplitPanel } from '@phosphor/widgets';
+
+import { BreakPointsWidget } from './breakpoints';
 
 import { Debugger } from './debugger';
 
-export class DebuggerSidebar extends Widget {
+import { CallstackWidget } from './callstack';
+
+import { VariablesWidget } from './variables';
+
+export class DebuggerSidebar extends SplitPanel {
   constructor(model: Debugger.Model | null) {
     super();
     this.model = model;
+    this.orientation = 'vertical';
     this.addClass('jp-DebuggerSidebar');
+
+    this.variables = new VariablesWidget();
+    this.callstack = new CallstackWidget();
+    this.breakPoints = new BreakPointsWidget();
+
+    this.addWidget(this.variables);
+    this.addWidget(this.callstack);
+    this.addWidget(this.breakPoints);
   }
 
+  readonly variables: VariablesWidget;
+
+  readonly callstack: CallstackWidget;
+
+  readonly breakPoints: BreakPointsWidget;
+
   get model(): Debugger.Model | null {
     return this._model;
   }

+ 4 - 0
src/variables/index.ts

@@ -0,0 +1,4 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export * from './widget';

+ 89 - 0
src/variables/model.ts

@@ -0,0 +1,89 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { Signal, ISignal } from '@phosphor/signaling';
+
+import { IVariable } from './variable';
+
+export interface IVariablesModel {
+  current: IVariable;
+  filter: string;
+  variables: IVariable[];
+  currentChanged: ISignal<Model, IVariable>;
+  variablesChanged: ISignal<Model, IVariable[]>;
+}
+
+export namespace IVariablesModel {
+  export function create(model: IVariable[]) {
+    return new Model(model);
+  }
+}
+
+export class Model implements IVariablesModel {
+  constructor(model: IVariable[]) {
+    this._state = model;
+  }
+
+  get currentChanged(): ISignal<this, IVariable> {
+    return this._currentChanged;
+  }
+
+  get current(): IVariable {
+    return this._current;
+  }
+  set current(variable: IVariable) {
+    if (this._current === variable) {
+      return;
+    }
+    this._current = variable;
+    this._currentChanged.emit(variable);
+  }
+
+  get filter() {
+    return this._filterState;
+  }
+  set filter(value) {
+    if (this._filterState === value) {
+      return;
+    }
+    this._filterState = value;
+    this._variablesChanged.emit(this._filterVariables());
+  }
+
+  get variables(): IVariable[] {
+    if (this._filterState) {
+      return this._filterVariables();
+    }
+    return this._state;
+  }
+  set variables(variables: IVariable[]) {
+    this._state = variables;
+  }
+
+  get variablesChanged(): ISignal<this, IVariable[]> {
+    return this._variablesChanged;
+  }
+
+  getCurrentVariables(): IVariable[] {
+    return this.variables;
+  }
+
+  fstFil(name: string): boolean {
+    return (
+      this._filterState
+        .split('')
+        .filter((ele: string, index: number) => name[index] === ele)
+        .join('') === this._filterState
+    );
+  }
+
+  private _filterVariables(): IVariable[] {
+    return this._state.filter(ele => this.fstFil(ele.name));
+  }
+
+  private _current: IVariable;
+  private _currentChanged = new Signal<this, IVariable>(this);
+  private _variablesChanged = new Signal<this, IVariable[]>(this);
+  private _filterState: string = '';
+  private _state: IVariable[];
+}

+ 6 - 0
src/variables/utils/index.ts

@@ -0,0 +1,6 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export * from './variableTableDescription';
+export * from './variableDescription';
+export * from './useTbody';

+ 4 - 0
src/variables/utils/toggle/index.ts

@@ -0,0 +1,4 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export * from './variableSearch';

+ 144 - 0
src/variables/utils/toggle/variableSearch.tsx

@@ -0,0 +1,144 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { ReactWidget } from '@jupyterlab/apputils';
+
+import { Panel, Widget } from '@phosphor/widgets';
+
+import React, { useState } from 'react';
+
+import { IVariablesModel } from '../../model';
+
+const SEARCH_ITEM = 'jp-Search-item';
+
+export class VariablesSearch extends Panel {
+  scope: Widget;
+  search: Widget;
+
+  constructor(model: any) {
+    super();
+    this.addClass('jp-DebuggerSidebarVariable-Search');
+    this.node.style.overflow = 'visible';
+    this.scope = new VariableScopeSearch();
+    this.search = new VariableSearchInput(model);
+    this.scope.addClass(SEARCH_ITEM);
+    this.scope.node.style.overflow = 'visible';
+    this.scope.node.style.width = '100px';
+    this.search.addClass(SEARCH_ITEM);
+    this.addWidget(this.scope);
+    this.addWidget(this.search);
+  }
+}
+
+const SearchComponent = ({ model }: any) => {
+  const [state, setState] = useState('');
+  model.filter = state;
+  return (
+    <div>
+      <input
+        placeholder="Search..."
+        className="jp-DebuggerSidebarVariable-Search-input"
+        value={state}
+        onChange={e => {
+          setState(e.target.value);
+        }}
+      />
+    </div>
+  );
+};
+
+class VariableSearchInput extends ReactWidget {
+  search: string;
+  model: IVariablesModel;
+  constructor(model: IVariablesModel) {
+    super();
+    this.model = model;
+    this.search = model.filter;
+  }
+
+  render() {
+    return <SearchComponent model={this.model} />;
+  }
+}
+
+const VariablesMenu = ({ config }: any) => {
+  const [toggleState, setToggle] = useState(false);
+  const [scope, setScope] = useState('local');
+
+  const toggle = (e: any) => {
+    setToggle(!toggleState);
+  };
+  const changeScope = (newScope: string) => {
+    if (newScope === scope) {
+      return;
+    }
+    setScope(newScope);
+    setToggle(false);
+  };
+
+  const List = (
+    <ul className="jp-MenuComponent">
+      <li onClick={e => changeScope('local')} className="jp-menu-item">
+        local
+      </li>
+      <li
+        className="jp-MenuComponent-item"
+        onClick={e => changeScope('global')}
+      >
+        global
+      </li>
+      <li
+        className="jp-MenuComponent-item"
+        onClick={e => changeScope('built-in')}
+      >
+        built-in
+      </li>
+    </ul>
+  );
+
+  return (
+    <div>
+      <span
+        onClick={e => toggle(e)}
+        className="jp-DebuggerSidebarVariable-Scope-label"
+      >
+        {scope}
+      </span>
+      <span className="fa fa-caret-down"></span>
+      {toggleState ? List : null}
+    </div>
+  );
+};
+
+class VariableScopeSearch extends ReactWidget {
+  showMenu() {
+    this._isOpen = !this._isOpen;
+    if (this._isOpen) {
+      // TODO
+    } else {
+      // no-op
+    }
+  }
+
+  render() {
+    return <VariablesMenu />;
+  }
+
+  private _isOpen = false;
+}
+
+// namespace Internal {
+//   export function createOptionsNode(): HTMLElement {
+//     const optionsIcon = document.createElement('span');
+//     optionsIcon.className = 'fa fa-caret-down';
+//     const optionLabel = document.createElement('span');
+
+//     const options = document.createElement('div');
+//     options.title = 'Options';
+//     optionLabel.innerText = 'local';
+//     optionLabel.className = 'jp-DebuggerSidebarVariable-Scope-label';
+//     options.appendChild(optionLabel);
+//     options.appendChild(optionsIcon);
+//     return options;
+//   }
+// }

+ 31 - 0
src/variables/utils/useTbody.tsx

@@ -0,0 +1,31 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import React, { useState } from 'react';
+
+const useTbody = (items: Array<any>, defaultState: any, id: string) => {
+  const [state, setState] = useState(defaultState);
+
+  const List = () => (
+    <tbody>
+      {items.map(item => (
+        <tr
+          key={item.name}
+          onClick={e => setState(item)}
+          className={id + (state === item ? ' selected' : '')}
+        >
+          <td style={{ paddingLeft: `${12}px`, width: `${25}%` }}>
+            {item.name}
+          </td>
+          <td style={{ paddingLeft: `${12}px`, width: `${75}%` }}>
+            {item.value}
+          </td>
+        </tr>
+      ))}
+    </tbody>
+  );
+
+  return [state, List, setState];
+};
+
+export default useTbody;

+ 57 - 0
src/variables/utils/variableDescription.ts

@@ -0,0 +1,57 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { Panel, SplitPanel, Widget } from '@phosphor/widgets';
+
+import { IVariablesModel } from '../model';
+
+import { IVariable } from '../variable';
+
+import { VariablesSearch } from './toggle';
+
+import { VariableTableDescription } from './variableTableDescription';
+
+export class VariableDescription extends Panel {
+  readonly searchParams: Widget;
+  readonly table: Panel;
+  readonly descriptionBox: Panel;
+
+  model: IVariablesModel;
+  currentVariable: any;
+
+  constructor(model: IVariablesModel) {
+    super();
+    this.model = model;
+    this.currentVariable = this.model.current;
+
+    this.searchParams = new VariablesSearch(this.model);
+    this.addWidget(this.searchParams);
+
+    this.table = new VariableTableDescription(this.model);
+    this.table.addClass('jp-DebuggerSidebarVariable-table');
+    this.addWidget(this.table);
+
+    this.descriptionBox = new SplitPanel();
+    this.descriptionBox.addClass('jp-DebuggerSidebarVariable-description');
+    this.addWidget(this.descriptionBox);
+    this.descriptionBox.node.innerHTML = '<b> Select Variable </b>';
+
+    this.model.currentChanged.connect(
+      (model: IVariablesModel, variable: IVariable) => {
+        this.descriptionBox.node.innerHTML = this.renderDescription(
+          this.model.current
+        );
+      }
+    );
+  }
+
+  // Still in progres: rendering description
+
+  protected renderDescription(variable: IVariable) {
+    const descriptionElementDOM = `<b>name: ${variable.name}</b>
+                                       <p>type: ${variable.type} </p>
+                                       Description:
+                                       <p>${variable.description}</p> `;
+    return descriptionElementDOM;
+  }
+}

+ 71 - 0
src/variables/utils/variableTableDescription.tsx

@@ -0,0 +1,71 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { ReactWidget } from '@jupyterlab/apputils';
+
+import { ArrayExt } from '@phosphor/algorithm';
+
+import { SplitPanel, Widget } from '@phosphor/widgets';
+
+import React, { useState } from 'react';
+
+import { IVariablesModel } from '../model';
+
+import useTbody from './useTbody';
+
+const ROW_CLASS = 'jp-DebuggerSidebarVariables-table-row';
+
+const HEAD_CLASS = 'jp-DebuggerSidebarVariables-table-head';
+
+const Table = ({ model }: { model: IVariablesModel }) => {
+  const [variables, setVariables] = useState(model.variables);
+  const [variable, TableBody] = useTbody(variables, model.current, ROW_CLASS);
+
+  model.variablesChanged.connect((_: any, updates) => {
+    if (ArrayExt.shallowEqual(variables, updates)) {
+      return;
+    }
+    setVariables(updates);
+  });
+
+  model.current = variable;
+  return (
+    <table>
+      <thead>
+        <tr>
+          <th style={{ width: '25%' }} className={HEAD_CLASS}>
+            Name
+          </th>
+          <th style={{ width: '75%' }} className={HEAD_CLASS}>
+            Value
+          </th>
+        </tr>
+      </thead>
+      <TableBody />
+    </table>
+  );
+};
+
+class TableVariableWidget extends ReactWidget {
+  state: IVariablesModel;
+
+  constructor(props: any) {
+    super(props);
+    this.state = props;
+  }
+
+  render() {
+    return <Table model={this.state} />;
+  }
+}
+
+export class VariableTableDescription extends SplitPanel {
+  private _model: IVariablesModel;
+
+  constructor(model: IVariablesModel) {
+    super();
+    this._model = model;
+    const myWidget: Widget = new TableVariableWidget(this._model);
+    this.addWidget(myWidget);
+  }
+}

+ 29 - 0
src/variables/variable.ts

@@ -0,0 +1,29 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+export interface IVariable {
+  /**
+   * The name of this variable.
+   */
+  readonly name: string;
+  /**
+   * The value of this variable.
+   */
+  readonly value: string;
+  /**
+   * The type of this variable.
+   */
+  readonly type: string | undefined;
+  /**
+   * The description of the variable.
+   */
+  readonly description: string | undefined;
+  /**
+   * a data URI or null.
+   */
+  readonly dataUri?: string;
+  /**
+   * a data URI or null.
+   */
+  readonly sourceUri?: string;
+}

+ 58 - 0
src/variables/widget.ts

@@ -0,0 +1,58 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { Panel } from '@phosphor/widgets';
+
+import { IVariablesModel } from './model';
+
+import { VariableDescription } from './utils';
+
+const MOCK_DATA_ROW = {
+  variables: [
+    {
+      name: 'test 1',
+      value: 'function()',
+      type: 'function',
+      description: 'def test1(): return 0'
+    },
+    {
+      name: 'test 2',
+      value: 'function()',
+      type: 'function',
+      description: 'def test2(): return 0'
+    }
+  ]
+};
+
+export class VariablesWidget extends Panel {
+  constructor() {
+    super();
+
+    this.model = IVariablesModel.create(MOCK_DATA_ROW.variables);
+
+    this.header = new Panel();
+    this.header.addClass('jp-DebuggerSidebarVariables-header');
+    this.addWidget(this.header);
+
+    this.label = new Panel();
+    this.label.node.textContent = 'Variables';
+    this.label.addClass('jp-DebuggerSidebarVariables-header-label');
+    this.header.addWidget(this.label);
+
+    this.variables = new VariableDescription(this.model);
+    this.variables.addClass('jp-DebuggerSidebarVariables-body');
+    this.addWidget(this.variables);
+  }
+
+  readonly body: Panel;
+
+  readonly header: Panel;
+
+  readonly label: Panel;
+
+  readonly model: IVariablesModel;
+
+  readonly searcher: Panel;
+
+  readonly variables: Panel;
+}

+ 16 - 0
style/icons.css

@@ -0,0 +1,16 @@
+/*-----------------------------------------------------------------------------
+| Copyright (c) Jupyter Development Team.
+| Distributed under the terms of the Modified BSD License.
+|----------------------------------------------------------------------------*/
+
+[data-jp-theme-light='true'] {
+  --jp-debugger-deactivate: url('./icons/md-light/baseline-label_off-24px.svg');
+}
+
+[data-jp-theme-light='false'] {
+  --jp-debugger-deactivate: url('./icons/md-dark/baseline-label_off-24px.svg');
+}
+
+.jp-DebuggerDeactivateIcon {
+  background-image: var(--jp-debugger-deactivate);
+}

+ 4 - 0
style/icons/md-dark/baseline-label_off-24px.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <path fill="none" d="M0 0h24v24H0V0z"/>
+    <path fill="#e0e0e0" d="M3.25 2.75l17 17L19 21l-2-2H5c-1.1 0-2-.9-2-2V7c0-.55.23-1.05.59-1.41L2 4l1.25-1.25zM22 12l-4.37-6.16C17.27 5.33 16.67 5 16 5H8l11 11 3-4z"/>
+</svg>

+ 1 - 0
style/icons/md-light/baseline-label_off-24px.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M3.25 2.75l17 17L19 21l-2-2H5c-1.1 0-2-.9-2-2V7c0-.55.23-1.05.59-1.41L2 4l1.25-1.25zM22 12l-4.37-6.16C17.27 5.33 16.67 5 16 5H8l11 11 3-4z"/></svg>

+ 209 - 2
style/index.css

@@ -3,8 +3,215 @@
 | Distributed under the terms of the Modified BSD License.
 |----------------------------------------------------------------------------*/
 
-.jp-DebuggerSidebar {
+@import './toolbar.css';
+
+.jp-Debugger {
   background: var(--jp-layout-color1);
   top: 0;
   bottom: 0;
-}
+}
+
+.jp-DebuggerSidebar {
+  display: flex;
+  flex-direction: column;
+  color: var(--jp-ui-font-color1);
+  background: var(--jp-layout-color1);
+  font-size: var(--jp-ui-font-size1);
+  min-width: 350px !important;
+}
+
+.jp-DebuggerSidebar div:not(:first-child) .jp-DebuggerSidebarVariables-header {
+  border-top: solid var(--jp-border-width) var(--jp-border-color1);
+}
+
+.jp-DebuggerSidebar div .jp-DebuggerSidebarVariables-header {
+  border-bottom: solid var(--jp-border-width) var(--jp-border-color1);
+}
+
+.jp-DebuggerSidebarVariables-header {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  background-color: var(--jp-layout-color2);
+  height: 24px;
+}
+
+.jp-DebuggerSidebarVariables-header-label {
+  text-transform: uppercase;
+  font-weight: 600;
+  font-size: var(--jp-ui-font-size0);
+  color: var(--jp-ui-font-color1);
+  padding-left: 8px;
+  padding-right: 4px;
+}
+
+.jp-DebuggerSidebarVariables-body {
+  border-bottom: solid var(--jp-border-width) var(--jp-border-color2);
+  min-height: 24px;
+  height: 99%;
+  display: flex;
+  flex-direction: column;
+}
+
+.jp-DebuggerSidebarVariable-table {
+  min-height: 50px;
+  flex-basis: 30%;
+}
+
+.jp-DebuggerSidebarVariable-table table {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.jp-DebuggerSidebarVariable-table .jp-DebuggerSidebarVariables-table-head {
+  margin-bottom: 4px;
+  border-top: var(--jp-border-width) solid var(--jp-border-color2);
+  border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
+  min-height: 23px;
+  padding: 4px 12px;
+  font-weight: 500;
+  text-align: left;
+}
+
+.jp-DebuggerSidebarVariables-table-head:hover,
+.jp-DebuggerSidebarVariables-table-row:hover {
+  background: var(--jp-layout-color2);
+}
+
+.jp-DebuggerSidebarVariables-table-row.selected {
+  color: white;
+  background: var(--jp-brand-color1);
+}
+
+.jp-DebuggerSidebarVariables-table-head
+  + .jp-DebuggerSidebarVariables-table-head {
+  border-left: var(--jp-border-width) solid var(--jp-border-color2);
+}
+
+.jp-DebuggerSidebarVariable-description {
+  border-top: var(--jp-border-width) solid var(--jp-border-color2);
+  min-height: 25px;
+  padding: 10px;
+}
+
+.jp-DebuggerSidebarVariable-description p {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+}
+
+.jp-DebuggerSidebarVariable-Search {
+  color: var(--jp-ui-font-color1);
+  flex: 0 0 auto;
+  display: flex;
+  flex-direction: row;
+  height: 24px;
+  /* height: calc(var(--jp-private-toolbar-height) + var(--jp-border-width)); */
+}
+
+.jp-DebuggerSidebarVariable-Search > .jp-Search-item {
+  flex: 0 0 auto;
+  padding-left: 8px;
+  padding-right: 8px;
+  vertical-align: middle;
+  font-size: 14px;
+  line-height: 23px;
+}
+
+.jp-DebuggerSidebarVariable-Search-input {
+  min-height: 22px;
+  vertical-align: top;
+  width: 100%;
+  height: 100%;
+  border: none;
+}
+
+.jp-DebuggerSidebarVariable-Scope-label {
+  padding-left: 10px;
+  padding-right: 5px;
+}
+
+/* callstack */
+
+.jp-DebuggerToolbar {
+  color: var(--jp-ui-font-color1);
+  flex: 0 0 auto;
+  display: flex;
+  flex-direction: row;
+  border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
+}
+
+.jp-DebuggerToolbar-item {
+  flex: 0 0 auto;
+  padding-left: 10px;
+  padding-right: 10px;
+  vertical-align: middle;
+  font-size: 14px;
+  line-height: 23px;
+  font-family: FontAwesome;
+  text-align: center;
+  display: inline-block;
+}
+
+/*  menu */
+
+.jp-MenuComponent {
+  position: absolute;
+  list-style: none;
+  left: 0;
+  right: 0;
+  margin: 0;
+  top: 25px;
+  z-index: 10000;
+  padding: 10px 10px;
+  background: var(--jp-layout-color1);
+  color: var(--jp-ui-font-color1);
+  border: var(--jp-border-width) solid var(--jp-border-color1);
+  font-size: var(--jp-ui-font-size1);
+  box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.2);
+}
+
+/* font awsome */
+
+.fa-active::before {
+  content: '\f04b';
+}
+
+.fa-stop::before {
+  content: '\f04d';
+}
+
+.fa-stepOver::before {
+  content: '\f050';
+}
+
+.fa-stepIn::before {
+  content: '\f150';
+}
+
+.fa-stepOut::before {
+  content: '\f151';
+}
+
+.fa-breakpoints.disactive::before {
+  content: '\f192';
+}
+
+.fa-breakpoints.active::before {
+  content: '\f111';
+}
+
+.fa-remove {
+  content: '\f057';
+}
+
+.fa {
+  display: inline-block;
+  font: normal normal normal 14px/1 FontAwesome;
+  font-size: inherit;
+  text-rendering: auto;
+  -webkit-font-smoothing: antialiased;
+}
+
+.fa-caret-down:before {
+  content: '\F0D7';
+}

+ 11 - 0
style/toolbar.css

@@ -0,0 +1,11 @@
+/*-----------------------------------------------------------------------------
+| Copyright (c) Jupyter Development Team.
+| Distributed under the terms of the Modified BSD License.
+|----------------------------------------------------------------------------*/
+
+@import './icons.css';
+
+.jp-DebuggerSidebar .jp-Toolbar {
+  background: var(--jp-layout-color2);
+  box-shadow: none;
+}

+ 1 - 1
tests/babel.config.js

@@ -1 +1 @@
-module.exports = require("@jupyterlab/testutils/lib/babel.config");
+module.exports = require('@jupyterlab/testutils/lib/babel.config');