diff --git a/package-lock.json b/package-lock.json
index b525edb49670fdcd7b3d06a4129d93315ee17edf..d776380d08693d18a0f0a0c65507f68ad75474bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8233,9 +8233,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
     },
     "lodash._reinterpolate": {
       "version": "3.0.0",
@@ -8559,9 +8559,9 @@
       }
     },
     "mixin-deep": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
-      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
       "requires": {
         "for-in": "^1.0.2",
         "is-extendable": "^1.0.1"
@@ -10643,6 +10643,11 @@
       "resolved": "https://registry.npmjs.org/react-numeric-input/-/react-numeric-input-2.2.3.tgz",
       "integrity": "sha1-S/WRjD6v7YUagN8euZLZQQArtVI="
     },
+    "react-pure-modal": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/react-pure-modal/-/react-pure-modal-1.5.1.tgz",
+      "integrity": "sha512-ac5H4D9D6W1Mi7IMyFoNGxht+uK/YhFkB0S10rG6ptHs9B7kTvYic718u9mRPDep0AWhonl/pWT3E97dTWlrcg=="
+    },
     "react-scripts": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.0.1.tgz",
@@ -11438,9 +11443,9 @@
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
     },
     "set-value": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
-      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
       "requires": {
         "extend-shallow": "^2.0.1",
         "is-extendable": "^0.1.1",
@@ -12556,35 +12561,14 @@
       }
     },
     "union-value": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
-      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
       "requires": {
         "arr-union": "^3.1.0",
         "get-value": "^2.0.6",
         "is-extendable": "^0.1.1",
-        "set-value": "^0.4.3"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "requires": {
-            "is-extendable": "^0.1.0"
-          }
-        },
-        "set-value": {
-          "version": "0.4.3",
-          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
-          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-extendable": "^0.1.1",
-            "is-plain-object": "^2.0.1",
-            "to-object-path": "^0.3.0"
-          }
-        }
+        "set-value": "^2.0.1"
       }
     },
     "uniq": {
diff --git a/package.json b/package.json
index 078fd8712c694c8243012fc6dc4451f558d43107..9a9a640694c54dccc094051436bb648ea95f898a 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
     "d3": "^5.8.0",
     "d3-scale": "^2.2.2",
     "flexlayout-react": "^0.3.3",
-    "lodash": "^4.17.11",
+    "lodash": "^4.17.15",
     "mobx": "^5.9.0",
     "mobx-react": "^5.4.3",
     "prop-types": "^15.7.2",
@@ -19,6 +19,7 @@
     "react-dom": "^16.7.0",
     "react-jsonschema-form": "^1.5.0",
     "react-numeric-input": "^2.2.3",
+    "react-pure-modal": "^1.5.1",
     "react-scripts": "^3.0.1",
     "react-sizeme": "^2.5.2",
     "roslib": "^1.0.1",
diff --git a/public/images/icons/add_circle_outline.svg b/public/images/icons/add_circle_outline.svg
new file mode 100644
index 0000000000000000000000000000000000000000..55d52d7b12e9cd1525726f729c30752deb0686ad
--- /dev/null
+++ b/public/images/icons/add_circle_outline.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" fill="#A1A1A1"/></svg>
diff --git a/src/Board.js b/src/Board/Board.js
similarity index 74%
rename from src/Board.js
rename to src/Board/Board.js
index 3de574c3ba1236a8cd0eb9011231899c0f030be0..77486e4de279954ceed3e8eb566281fbb424f67c 100755
--- a/src/Board.js
+++ b/src/Board/Board.js
@@ -2,23 +2,45 @@ import React from 'react';
 // Tab-based dynamic layout manager
 import FlexLayout from 'flexlayout-react';
 // MobX, a state manager
-import {toJS} from 'mobx'
+import {reaction, toJS} from 'mobx'
 import {observer} from 'mobx-react'
 // The React Components that are going into tabs
-import {VideoStream, DemoVideoStream} from './VideoStream'
-import {RosLineChart, DemoLineChart} from './LineChart'
-import {RosHGauge} from './HorizontalGauge'
-import {RosMemoryRanked, DemoMemoryRanked} from './MemoryRanked'
-import {RosInteractionTrace, DemoInteractionTrace} from './InteractionTrace'
-import {RosLatestInteraction, DemoLatestInteraction} from './LatestInteraction'
-import {RosMood, DemoMood} from './Mood'
-import {Graph, DemoGraph} from './GraphVisJs'
-import DemoString from './String'
+import {VideoStream, DemoVideoStream} from '../VideoStream'
+import {RosLineChart, DemoLineChart} from '../LineChart'
+import {RosHGauge} from '../HorizontalGauge'
+import {RosMemoryRanked, DemoMemoryRanked} from '../MemoryRanked'
+import {RosInteractionTrace, DemoInteractionTrace} from '../InteractionTrace'
+import {RosLatestInteraction, DemoLatestInteraction} from '../LatestInteraction'
+import {RosMood, DemoMood} from '../Mood'
+import {Graph, DemoGraph} from '../GraphVisJs'
+import DemoString from '../String'
+// A component used to display the readme or config form for the widgets
+import {GadgetModal} from '../utils/GadgetModal';
 
 // get the default configuration for the layout
-import {flexlayout_json as json} from './demo-1-config'
-// import {flexlayout_json as json} from './demo-tabbed-config'
-// import {flexlayout_json as json} from './devel-config'
+import {flexlayout_json as json} from '../demo-1-config'
+// import {flexlayout_json as json} from '../demo-tabbed-config'
+// import {flexlayout_json as json} from '../devel-config'
+
+
+export const tab_types = {
+    "video": VideoStream,
+    "demo-video": DemoVideoStream,
+    "line-chart": RosLineChart,
+    "demo-line-chart": DemoLineChart,
+    "h-gauge": RosHGauge,
+    "memory": RosMemoryRanked,
+    "demo-memory": DemoMemoryRanked,
+    "int-trace": RosInteractionTrace,
+    "demo-int-trace": DemoInteractionTrace,
+    "string": DemoString,
+    "demo-latest-interaction": DemoLatestInteraction,
+    "latest-interaction": RosLatestInteraction,
+    "mood": RosMood,
+    "demo-mood": DemoMood,
+    "graph": Graph,
+    "demo-graph": DemoGraph,
+}
 
 const Board = observer(
 class Board extends React.Component {
@@ -26,6 +48,8 @@ class Board extends React.Component {
         super(props)
         this.state = {model: FlexLayout.Model.fromJson(json)}
 
+        reaction(() => this.props.store.sharedData.get('newTab'), this.addTab.bind(this));
+
         this.refLayout = React.createRef();
     }
 
@@ -34,25 +58,6 @@ class Board extends React.Component {
      * @param node node to be added, as per the vocabulary of FlexLayout
      */
     factory(node) {
-        const tab_types = {
-            "video": VideoStream,
-            "demo-video": DemoVideoStream,
-            "line-chart": RosLineChart,
-            "demo-line-chart": DemoLineChart,
-            "h-gauge": RosHGauge,
-            "memory": RosMemoryRanked,
-            "demo-memory": DemoMemoryRanked,
-            "int-trace": RosInteractionTrace,
-            "demo-int-trace": DemoInteractionTrace,
-            "string": DemoString,
-            "demo-latest-interaction": DemoLatestInteraction,
-            "latest-interaction": RosLatestInteraction,
-            "mood": RosMood,
-            "demo-mood": DemoMood,
-            "graph": Graph,
-            "demo-graph": DemoGraph,
-        }
-
         /** This function gives the React Component correspinding to a tab type.
          *
          * A set of React components are mapped to "tab types" (which are strings). Hence, the tab type "video" maps
@@ -77,12 +82,15 @@ class Board extends React.Component {
         }, null);
     }
 
-    onAdd(event) {
-        this.refLayout.current.addTabWithDragAndDropIndirect("Add panel<br>(Drag to location)", {
-            component: "h-gauge",
-            name: "added",
-            config: {value: 0.5}
-        }, null);
+    addTab() {
+        if (this.props.store.sharedData.has('newTab')) {
+            const {component, name} = this.props.store.sharedData.get('newTab');
+            this.refLayout.current.addTabWithDragAndDrop(`Add ${name}<br>(Drag to location)`, {
+                component: component,
+                name: name
+            }, null);
+            this.props.store.sharedData.delete('newTab')
+        }
     }
 
     /**
@@ -123,7 +131,9 @@ class Board extends React.Component {
                     // If no modal is active, display the relevant one;
                     // otherwise, get out of it.
                     if (!this.props.store.modal.enabled) {
-                        this.props.store.displayModal(modeName, selectedTab.getId());
+                        this.props.store.displayModal(
+                            <GadgetModal store={this.props.store} component={selectedTab.getId()} mode={modeName}/>
+                        );
                     } else {
                         this.props.store.exitModal();
                     }
diff --git a/src/Board/NewWidget.js b/src/Board/NewWidget.js
new file mode 100644
index 0000000000000000000000000000000000000000..b7f2d6f537b000340c19a9334eceb525a9556695
--- /dev/null
+++ b/src/Board/NewWidget.js
@@ -0,0 +1,100 @@
+import React from 'react';
+import {decorate, observable} from 'mobx'
+import {observer} from 'mobx-react'
+import {map} from 'lodash'
+
+// Mappings from 'string' types (as per tab_types in Board.js) and display names of the available widgets.
+const tab_names = {
+  "video": "Video stream",
+  "line-chart": "Simple line chart",
+  "h-gauge": "Gauge",
+  "memory": "Agent's memory",
+  "int-trace": "Interaction trace",
+  "latest-interaction": "Latest interaction",
+  "mood": "Current mood",
+  "graph": "Graph"
+}
+const demo_tab_names = {
+  "demo-video": "Video stream demo",
+  "demo-line-chart": "Line chart demo",
+  "demo-memory": "Agent's memory demo",
+  "demo-int-trace": "Interaction trace demo",
+  "demo-latest-interaction": "Latest interaction demo",
+  "demo-mood": "Current mood demo",
+  "demo-graph": "Graph demo",
+  "string": "ROS debug",
+}
+
+/**
+ * This React component appears in a modal, once we click on the '+' button in the menu. It offers the user to choose
+ * which component he/she wants to add to the dashboard.
+ */
+export const NewWidget = observer(
+class NewWidget extends React.Component {
+  selected = Object.keys(tab_names)[0];
+  enableDemoWidgets = false;
+
+  /**
+   * Set the data for a new tab/widget to be added in the dashboard. This will trigger a method in Board.js, thanks to
+   * Mobx's magic. It also closes this modal.
+   */
+  addTab() {
+    this.props.store.sharedData.set('newTab', {
+      component: this.selected,
+      name: tab_names[this.selected]
+    });
+    this.props.store.exitModal();
+  }
+
+  /**
+   * This method is used to generate radio inputs for the widgets we offer the user to add to the dashboard. It's
+   * called in a map (Lodash style).
+   * @param {string} name Display name of the widget
+   * @param {string} type string for the type of the widget, as used in Board.js' tab_types
+   */
+  inputFromTabName(name, type) {
+    return (
+      <div key={type}>
+        <label>
+          <input
+            type="radio"
+            name="component-type"
+            value={type}
+            checked={type === this.selected}
+            onChange={(changeEvent) => {this.selected = changeEvent.target.value}}
+          />
+          &nbsp;{name}
+        </label>
+      </div>
+    );
+  }
+
+  render() {
+    let inputs = map(tab_names, this.inputFromTabName.bind(this));
+    // if the user chose to see the demo widgets, add these to the list
+    if (this.enableDemoWidgets) {
+      inputs.push(map(demo_tab_names, this.inputFromTabName.bind(this)));
+    }
+
+    return (
+      <div>
+        {inputs}
+
+        <label>
+          <input
+            type="checkbox"
+            checked={this.enableDemoWidgets}
+            onChange={(changeEvent) => {this.enableDemoWidgets = changeEvent.target.checked;}}
+          />
+          &nbsp;Show demo widgets
+        </label><br/>
+
+        <button onClick={this.addTab.bind(this)}>Add to the dashboard</button>
+      </div>
+    )
+  }
+})
+decorate(NewWidget, {
+  selected: observable,
+  enableDemoWidgets: observable,
+})
diff --git a/src/Menu/Menu.css b/src/Menu/Menu.css
index 03775738a72944038975928736e5ee47aa4b2adf..99e5148ed31117d09daff0bb1d771f0e7041f98b 100644
--- a/src/Menu/Menu.css
+++ b/src/Menu/Menu.css
@@ -75,11 +75,23 @@
 }
 
 .lock-button {
-  margin-left:70px;
+  margin-left: 70px;
 }
 
 .about-button {
-  margin-left:30px;
+  margin-left: 30px;
+}
+
+.add-button {
+  margin-left: 50px;
+  position: fixed;
+  bottom: 5vh;
+  display: inline-block;
+}
+
+.add-button:hover {
+  filter: invert(67%) sepia(71%) saturate(551%) hue-rotate(1deg) brightness(111%) contrast(86%);
+  cursor: pointer;
 }
 
 .sidenav---sidenav---_2tBP.sidenav---expanded---1KdUL .title {
diff --git a/src/Menu/index.js b/src/Menu/index.js
index 7cb5bf297de22215ea4f76f13c003807cd16acac..cf3aa45e8c951163fd898214c643bf7a8f3a987f 100644
--- a/src/Menu/index.js
+++ b/src/Menu/index.js
@@ -1,10 +1,33 @@
 import React from "react";
-
+import {observer} from "mobx-react";
 import SideNav, { NavItem, NavIcon, NavText } from '@trendmicro/react-sidenav';
 import './Menu.css'
 
+import {NewWidget} from '../Board/NewWidget'
+
+
+export const Menu = observer(
+function Menu(props) {
+  const lock = props.store.sharedData.get('lock') || 'closed';
+  function toggle_lock() {
+    const new_value = (lock === 'closed') ? 'open' : 'closed';
+    props.store.sharedData.set('lock', new_value);
+  }
+
+  function add_widget() {
+    props.store.displayModal(<NewWidget store={props.store}/>);
+  }
+  // Display an "add" icon if the lock is open. This icon is used to add new widgets to the dashboard.
+  let add_button = null;
+  if (lock === 'open') {
+    add_button = (
+      <img className="footer add-button"
+        onClick={add_widget}
+        src={window.location.origin + "/images/icons/add_circle_outline.svg"}
+        alt="add a new widget"
+      />);
+  }
 
-export function Menu(props) {
   return(
 
     <SideNav
@@ -29,12 +52,10 @@ export function Menu(props) {
 
         <NavItem eventKey="demo">
           <NavIcon>
-            {/* <a href="#"> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/dashboard-grey.svg"}
-                alt="Demo mode"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/dashboard-grey.svg"}
+              alt="Demo mode"
+            />
           </NavIcon>
           <NavText>
             Demo
@@ -51,12 +72,10 @@ export function Menu(props) {
 
         <NavItem eventKey="memory">
           <NavIcon>
-            {/* <a> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/memory-grey.svg"}
-                alt="memory dashboard"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/memory-grey.svg"}
+              alt="memory dashboard"
+            />
           </NavIcon>
           <NavText>
             Memory
@@ -65,12 +84,10 @@ export function Menu(props) {
 
         <NavItem eventKey="traces">
           <NavIcon>
-            {/* <a> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/trace-grey.svg"}
-                alt="trace dashboard"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/trace-grey.svg"}
+              alt="trace dashboard"
+            />
           </NavIcon>
           <NavText>
             Traces
@@ -79,12 +96,10 @@ export function Menu(props) {
 
         <NavItem eventKey="mental-states">
           <NavIcon>
-            {/* <a> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/mood-grey.svg"}
-                alt="mood dashboard"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/mood-grey.svg"}
+              alt="mood dashboard"
+            />
           </NavIcon>
           <NavText>
             Mental states
@@ -93,12 +108,10 @@ export function Menu(props) {
 
         <NavItem eventKey="decision-making">
           <NavIcon>
-            {/* <a> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/choice-grey.svg"}
-                alt="choice dashboard"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/choice-grey.svg"}
+              alt="choice dashboard"
+            />
           </NavIcon>
           <NavText>
             Decision making
@@ -111,12 +124,10 @@ export function Menu(props) {
 
         <NavItem eventKey="video">
           <NavIcon>
-            {/* <a> */}
-              <img className="menu-button"
-                src={window.location.origin + "/images/icons/video-grey.svg"}
-                alt="video dashboard"
-              />
-            {/* </a> */}
+            <img className="menu-button"
+              src={window.location.origin + "/images/icons/video-grey.svg"}
+              alt="video dashboard"
+            />
           </NavIcon>
           <NavText>
             Video
@@ -125,12 +136,10 @@ export function Menu(props) {
 
         <NavItem eventKey="audio">
           <NavIcon>
-            {/* <a> */}
               <img className="menu-button"
                 src={window.location.origin + "/images/icons/microphone-grey.svg"}
                 alt="microphone dashboard"
               />
-            {/* </a> */}
           </NavIcon>
           <NavText>
             Audio
@@ -139,18 +148,18 @@ export function Menu(props) {
 
         <NavItem eventKey="sensory">
           <NavIcon>
-            {/* <a> */}
               <img className="menu-button"
                 src={window.location.origin + "/images/icons/fingerprint-grey.svg"}
                 alt="sensory dashboard"
               />
-            {/* </a> */}
           </NavIcon>
           <NavText>
             Sensory
           </NavText>
         </NavItem>
 
+        {add_button}
+
         <a href="more.html">
           <img className="footer menu-button about-button"
             src={window.location.origin + "/images/icons/about.svg"}
@@ -158,13 +167,12 @@ export function Menu(props) {
           />
         </a>
 
-        {/* <a> */}
-          <img className="footer menu-button lock-button"
-            src={window.location.origin + "/images/icons/lock_closed-grey.svg"}
-            alt="lock/unlock the dashboard"
-          />
-        {/* </a> */}
+        <img className="footer menu-button lock-button"
+          src={window.location.origin + "/images/icons/lock_" + lock + "-grey.svg"}
+          alt="lock/unlock the dashboard"
+          onClick={toggle_lock}
+        />
       </SideNav.Nav>
     </SideNav>
   )
-}
+})
diff --git a/src/index.js b/src/index.js
index 7d2c6311c71fd49f4041c843b693b143c9f91121..4a283e657ca8044feb2bf1db0ce6e84489fda65b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,15 +1,17 @@
 import React from "react";
 import ReactDOM from "react-dom";
+// A little library to display modals on top of the page
+import PureModal from 'react-pure-modal';
+import 'react-pure-modal/dist/react-pure-modal.min.css';
 // MobX, a state manager
 import {decorate, observable} from "mobx"
 import {observer} from 'mobx-react'
 // ROS library
 import RosLib from 'roslib';
 // React Components to be displayed
-import {Board} from './Board';
+import {Board} from './Board/Board';
 import {Header} from './Header';
 import {Menu} from "./Menu";
-import {Modal} from './utils/modeModal';
 
 import 'bootstrap/dist/css/bootstrap.min.css'
 // CSS common to the whole app
@@ -20,12 +22,10 @@ class ObservableStore {
   sharedData = observable.map()
   modal = {
     enabled: false,
-    mode: null,
     component: null,
   }
-  displayModal(mode, component) {
+  displayModal(component) {
     this.modal.enabled = true;
-    this.modal.mode = mode;
     this.modal.component = component;
   }
   exitModal() {
@@ -33,6 +33,7 @@ class ObservableStore {
     this.modal.mode = null;
     this.modal.component = null;
   }
+  dragging = false
 }
 decorate(ObservableStore, {
   components: observable,
@@ -67,25 +68,36 @@ class Main extends React.Component {
     }
   }
 
+  // When the esc key is pressed, if the modal is enabled, disable it
+  handleKeyDown = (event) => {
+    if(event.keyCode === 27 && this.store.modal.enabled === true) {
+      this.store.modal.enabled = false;
+    }
+  }
+
+  componentDidMount(){
+    document.addEventListener("keydown", this.handleKeyDown, false);
+  }
+
   componentWillUnmount() {
-      if (this.ros) {
-          this.ros.close()
-      }
+    if (this.ros) {
+      this.ros.close()
+    }
+
+    document.removeEventListener("keydown", this.handleKeyDown, false);
   }
 
   render() {
-    let modal = null;
-    if (this.store.modal.enabled) {
-      modal = (
-      <div id="overlay" tabIndex="-1" role="dialog">
-        <Modal store={this.store}/>
-      </div>);
+    function addTab(component, name) {
+      return () => {
+        this.store.sharedData.set('newTab', {component: component, name: name});
+      }
     }
 
     return (
       <div id="level-1">
         <div id="menu">
-          <Menu ros={this.ros}/>
+          <Menu ros={this.ros} store={this.store} drag={addTab.bind(this)}/>
         </div>
         <div id="level-2">
           <div id="header">
@@ -95,7 +107,14 @@ class Main extends React.Component {
             <Board ros={this.ros} store={this.store}/>
           </div>
         </div>
-        {modal}
+        <PureModal
+          width = "700px"
+          onClose={() => {this.store.modal.enabled = false}}
+          isOpen = {this.store.modal.enabled}
+          ref="modal"
+          >
+          {this.store.modal.component}
+        </PureModal>
       </div>
     )
   }
diff --git a/src/utils/modeModal.js b/src/utils/GadgetModal.js
similarity index 93%
rename from src/utils/modeModal.js
rename to src/utils/GadgetModal.js
index 544a581d919d1710a1b2b4f320bba56298f10f42..db8ec3afa34e58ff672ea5fc4c7da0fbcbdb6e8c 100644
--- a/src/utils/modeModal.js
+++ b/src/utils/GadgetModal.js
@@ -5,19 +5,19 @@ import { merge } from 'lodash/object';
 /**
  * This component displays either the readme information about a component or a form to change the settings of a
  * component.
- * 
+ *
  * All changes to the node's settings are saved through a mobX store (passed as props).
- * 
- * Expected React properties : 
+ *
+ * Expected React properties:
  *  - node: as provided by the `Board` component to all its children
  *  - store: object containing information about all relevant React components, as well as information on the current
  *      mode.
  */
-export class Modal extends Component {
+export class GadgetModal extends Component {
     constructor(props) {
         super(props);
-        
-        this.component = this.props.store.components[this.props.store.modal.component];
+
+        this.component = this.props.store.components[this.props.component];
         this.hasReadme = 'readme' in this.component;
         this.configurable = 'configSchema' in this.component;
     }
@@ -27,7 +27,7 @@ export class Modal extends Component {
      * attribute of the modal's configuration.
      */
     render() {
-      const mode = this.props.store.modal.mode;
+      const mode = this.props.mode;
       if (this.configurable && mode === "settings") {
         return [
           <Form
@@ -64,5 +64,5 @@ export class Modal extends Component {
         this.props.store.exitModal();
         return config;
     }
-    
+
 }