From b33e45f1f839b3c6eaf1076e605abacd1bc6883c Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 29 Jul 2021 15:35:39 -0400
Subject: lots of updates!

---
 src/client/views/topbar/TopBar.tsx | 58 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 src/client/views/topbar/TopBar.tsx

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
new file mode 100644
index 000000000..79239d4ea
--- /dev/null
+++ b/src/client/views/topbar/TopBar.tsx
@@ -0,0 +1,58 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import * as React from 'react';
+import { Doc, DocListCast } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
+import { StrCast } from '../../../fields/Types';
+import { Utils } from '../../../Utils';
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
+import { ColorScheme, SettingsManager } from "../../util/SettingsManager";
+import { undoBatch } from "../../util/UndoManager";
+import "./TopBar.scss";
+import { Colors, Borders } from "../global/globalEnums";
+
+export const TopBar = () => {
+
+    const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data);
+    return (
+        <div style={{ pointerEvents: "all" }} className="topbar-container">
+            <div className="topbar-bar" style={{ background: Doc.UserDoc().colorScheme === ColorScheme.Dark ? Colors.DARK_GRAY : Colors.LIGHT_GRAY, borderBottom: Borders.STANDARD }}>
+                <div className="topbar-center" >
+                    <div className="topbar-lozenge-dashboard">
+                        <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
+                            value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)}
+                            style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
+                            {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
+                        </select>
+                        <div className="topbar-dashboards">
+                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
+                                style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
+                                <FontAwesomeIcon icon="plus"></FontAwesomeIcon>
+                            </div>
+                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
+                                style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
+                                <FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div className="topbar-right" >
+                    <div className="topbar-icon"
+                        style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
+                        <FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
+                    </div>
+                    <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}
+                        style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
+                        <FontAwesomeIcon icon="cog"></FontAwesomeIcon>
+                    </div>
+                    <div className="topbar-lozenge-user">
+                        {`${Doc.CurrentUserEmail}`}
+                        <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+                            Logoff
+                        </div>
+                    </div>
+                </div>
+
+            </div >
+        </div >
+    );
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From c9f379adab864132e6cf044f808a43254601e4bb Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Fri, 30 Jul 2021 13:26:25 -0400
Subject: major UI / updates + refactoring

---
 deploy/assets/favicon.png                          |  Bin 0 -> 22180 bytes
 deploy/index.html                                  |  114 +-
 deploy/loader.css                                  |   85 +
 deploy/loader.js                                   |   14 +
 src/client/documents/Documents.ts                  |    4 +-
 src/client/util/CurrentUserUtils.ts                |   44 +-
 src/client/views/AntimodeMenu.scss                 |    1 +
 src/client/views/DocumentButtonBar.tsx             |    2 +-
 src/client/views/MainView.scss                     |   30 +-
 src/client/views/MainView.tsx                      |   29 +-
 src/client/views/PropertiesView.tsx                |    2 +-
 src/client/views/_nodeModuleOverrides.scss         |    4 +-
 src/client/views/collections/CollectionMenu.scss   |    4 +-
 src/client/views/collections/CollectionMenu.tsx    |    2 +-
 src/client/views/collections/TabDocView.tsx        |    2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   10 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |    3 +-
 src/client/views/global/globalCssVariables.scss    |    3 +
 src/client/views/nodes/DocumentContentsView.tsx    |    4 +-
 src/client/views/nodes/DocumentView.tsx            |    2 +-
 src/client/views/nodes/FontIconBox.tsx             |    3 +-
 src/client/views/nodes/PresBox.scss                | 1243 ----------
 src/client/views/nodes/PresBox.tsx                 | 2472 --------------------
 .../views/nodes/formattedText/RichTextMenu.tsx     |   10 +-
 src/client/views/nodes/trails/PresBox.scss         | 1243 ++++++++++
 src/client/views/nodes/trails/PresBox.tsx          | 2440 +++++++++++++++++++
 src/client/views/nodes/trails/PresElementBox.scss  |  235 ++
 src/client/views/nodes/trails/PresElementBox.tsx   |  388 +++
 src/client/views/nodes/trails/PresEnums.ts         |   28 +
 src/client/views/nodes/trails/index.ts             |    3 +
 .../views/presentationview/PresElementBox.scss     |  235 --
 .../views/presentationview/PresElementBox.tsx      |  386 ---
 src/client/views/topbar/TopBar.scss                |   12 +-
 src/client/views/topbar/TopBar.tsx                 |   89 +-
 tslint.json                                        |   41 +-
 35 files changed, 4587 insertions(+), 4600 deletions(-)
 create mode 100644 deploy/assets/favicon.png
 create mode 100644 deploy/loader.css
 create mode 100644 deploy/loader.js
 delete mode 100644 src/client/views/nodes/PresBox.scss
 delete mode 100644 src/client/views/nodes/PresBox.tsx
 create mode 100644 src/client/views/nodes/trails/PresBox.scss
 create mode 100644 src/client/views/nodes/trails/PresBox.tsx
 create mode 100644 src/client/views/nodes/trails/PresElementBox.scss
 create mode 100644 src/client/views/nodes/trails/PresElementBox.tsx
 create mode 100644 src/client/views/nodes/trails/PresEnums.ts
 create mode 100644 src/client/views/nodes/trails/index.ts
 delete mode 100644 src/client/views/presentationview/PresElementBox.scss
 delete mode 100644 src/client/views/presentationview/PresElementBox.tsx

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/deploy/assets/favicon.png b/deploy/assets/favicon.png
new file mode 100644
index 000000000..59595b910
Binary files /dev/null and b/deploy/assets/favicon.png differ
diff --git a/deploy/index.html b/deploy/index.html
index dda0c6457..d96215391 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -1,114 +1,22 @@
 <html style="overflow: hidden;">
 
 <head>
-    <title>Dash Web</title>
-    <link href="https://fonts.googleapis.com/css?family=Fjalla+One|Hind+Siliguri:300" rel="stylesheet">
-    <link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500' rel='stylesheet'>
+    <title>Dash</title>
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link
+        href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&family=Lato:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Merriweather:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&family=Roboto:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap"
+        rel="stylesheet">
+    <link rel="shortcut icon" type="image/jpg" href="./assets/favicon.png" />
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
         integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
     <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script>
-
-    <script>
-        function getCookie(cname) {
-            var name = cname + "=";
-            var ca = document.cookie.split(';');
-            for (var i = 0; i < ca.length; i++) {
-                var c = ca[i];
-                while (c.charAt(0) == ' ') {
-                    c = c.substring(1);
-                }
-                if (c.indexOf(name) == 0) {
-                    return Number(c.substring(name.length, c.length));
-                }
-            }
-            return 3000;
-        } 
-    </script>
-    <style>
-        .dash-loader {
-            display: flex;
-            align-content: center;
-            justify-content: center;
-            background-color: #AEDDF8;
-            transition: 3s;
-            z-index: 10;
-            width: 100vw;
-            height: 100vh;
-        }
-
-        .dash-loader-container {
-            display: grid;
-            grid-auto-rows: auto 30px auto;
-        }
-
-        .dash-progress-bar {
-            width: 200px;
-            height: 5px;
-            align-self: center;
-            margin-top: 20px;
-            background-color: #ececec;
-            border-radius: 5px;
-            overflow: hidden;
-        }
-
-        .dash-progress {
-            width: 0%;
-            height: 20px;
-            background-color: #5b9fdd;
-            transition: 0.1s;
-        }
-
-        .dash-animation-container {
-            width: 10vw;
-            height: 10vw;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            border-radius: 100%;
-            background-color: #5B9FDD;
-            justify-self: center;
-            align-self: flex-end;
-        }
-
-        .dash-loader-text {
-            font-size: 15px;
-            font-family: "Roboto";
-            text-align: center;
-            color: #5B9FDD;
-        }
-
-        .dash-d-path {
-            stroke-dasharray: 1000;
-            stroke-dashoffset: 1000;
-            animation: dash-d-path 3s linear infinite;
-        }
-
-        @keyframes dash-d-path {
-            0% {
-                stroke-dashoffset: 1000;
-            }
-
-            20% {
-                stroke-dashoffset: 0;
-            }
-
-            70% {
-                stroke-dashoffset: 0;
-            }
-
-            90% {
-                stroke-dashoffset: 1000;
-            }
-
-            100% {
-                stroke-dashoffset: 1000;
-            }
-        }
-    </style>
+    <script src="loader.js"></script>
+    <link rel="stylesheet" href="./loader.css" />
 </head>
 
 <body style="display:flex" id="dash-body">
-    <div class="dash-loader" id="loader" style="z-index:10; width:100%; height:100%;">
+    <div class="dash-loader" id="loader">
         <div class="dash-loader-container">
             <div class="dash-animation-container">
                 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px"
@@ -127,7 +35,7 @@
                     console.log("Last Load = " + load);
                     let dashmesg = (width, msg) => {
                         if (document.getElementById("dash-progress")) document.getElementById("dash-progress").style.width = width
-                        if (document.getElementById("dash-progress")) document.getElementById("dash-progress").innerHTML = msg
+                        if (document.getElementById("dash-progress")) document.getElementById("dash-loader-text").innerHTML = msg
                     }
                     setTimeout(() => dashmesg("10%", "Loading Dash..."), load / 10);
                     setTimeout(() => dashmesg("33%", "Preparing dashboards..."), load / 3);
diff --git a/deploy/loader.css b/deploy/loader.css
new file mode 100644
index 000000000..4be0cc98c
--- /dev/null
+++ b/deploy/loader.css
@@ -0,0 +1,85 @@
+.dash-loader {
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    background-color: #BDDDF5;
+    transition: 3s;
+    z-index: 10;
+    z-index:10; 
+    width:100%;
+    height:100%;
+}
+
+.dash-loader-container {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    align-content: center;
+}
+
+.dash-progress-bar {
+    width: 200px;
+    height: 5px;
+    align-self: center;
+    margin-top: 20px;
+    background-color: #ececec;
+    border-radius: 5px;
+    overflow: hidden;
+}
+
+.dash-progress {
+    width: 0%;
+    height: 20px;
+    background-color: #4476F7;
+    transition: 0.1s;
+}
+
+.dash-animation-container {
+    width: 10vw;
+    height: 10vw;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 100%;
+    background-color: #4476F7;
+    justify-self: center;
+}
+
+.dash-loader-text {
+    font-size: 15px;
+    font-family: "Roboto";
+    font-weight: bold;
+    text-align: center;
+    color: #4476F7;
+    user-select: none;
+    -webkit-user-select: none;
+}
+
+.dash-d-path {
+    stroke-dasharray: 1000;
+    stroke-dashoffset: 1000;
+    animation: dash-d-path 3s linear infinite;
+}
+
+@keyframes dash-d-path {
+    0% {
+        stroke-dashoffset: 1000;
+    }
+
+    20% {
+        stroke-dashoffset: 0;
+    }
+
+    70% {
+        stroke-dashoffset: 0;
+    }
+
+    90% {
+        stroke-dashoffset: 1000;
+    }
+
+    100% {
+        stroke-dashoffset: 1000;
+    }
+}
\ No newline at end of file
diff --git a/deploy/loader.js b/deploy/loader.js
new file mode 100644
index 000000000..0be421e14
--- /dev/null
+++ b/deploy/loader.js
@@ -0,0 +1,14 @@
+function getCookie(cname) {
+    var name = cname + "=";
+    var ca = document.cookie.split(';');
+    for (var i = 0; i < ca.length; i++) {
+        var c = ca[i];
+        while (c.charAt(0) == ' ') {
+            c = c.substring(1);
+        }
+        if (c.indexOf(name) == 0) {
+            return Number(c.substring(name.length, c.length));
+        }
+    }
+    return 3000;
+} 
\ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f1db3e32c..81465a241 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -45,14 +45,14 @@ import { LabelBox } from "../views/nodes/LabelBox";
 import { LinkBox } from "../views/nodes/LinkBox";
 import { LinkDescriptionPopup } from "../views/nodes/LinkDescriptionPopup";
 import { PDFBox } from "../views/nodes/PDFBox";
-import { PresBox } from "../views/nodes/PresBox";
+import { PresBox } from "../views/nodes/trails/PresBox";
 import { ScreenshotBox } from "../views/nodes/ScreenshotBox";
 import { ScriptingBox } from "../views/nodes/ScriptingBox";
 import { SliderBox } from "../views/nodes/SliderBox";
 import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox";
 import { VideoBox } from "../views/nodes/VideoBox";
 import { WebBox } from "../views/nodes/WebBox";
-import { PresElementBox } from "../views/presentationview/PresElementBox";
+import { PresElementBox } from "../views/nodes/trails/PresElementBox";
 import { SearchBox } from "../views/search/SearchBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
 import { DocumentType } from "./DocumentTypes";
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 22504f102..62fab1b23 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -35,6 +35,8 @@ import { UndoManager } from "./UndoManager";
 import { SnappingManager } from "./SnappingManager";
 import { InkTool } from "../../fields/InkField";
 import { computedFn } from "mobx-utils";
+import { ColorScheme } from "./SettingsManager";
+import { Colors } from "../views/global/globalEnums";
 
 
 export let resolvedPorts: { server: number, socket: number };
@@ -472,7 +474,7 @@ export class CurrentUserUtils {
             { toolTip: "Tap to create a videoWall", title: "Wall", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWall as Doc },
             { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
             { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc },
-            { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
+            // { toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
             { toolTip: "Tap to create a scripting box in a new pane, drag for a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScript as Doc },
             { toolTip: "Tap to create a mobile view in a new pane, drag for a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc },
             { toolTip: "Tap to create a custom header note document, drag for a custom header note", title: "Custom", icon: "window-maximize", click: 'openOnRight(delegateDragFactory(this.dragFactory))', drag: 'delegateDragFactory(this.dragFactory)', dragFactory: doc.emptyHeader as Doc },
@@ -534,8 +536,8 @@ export class CurrentUserUtils {
             { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
             // { title: "Filter", target: Cast(doc.currentFilter, Doc, null), icon: "filter", click: 'selectMainMenu(self)' },
             { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
-            { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
-            { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
+            // { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
+            // { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
             { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
         ];
     }
@@ -561,7 +563,6 @@ export class CurrentUserUtils {
                     dontUndo: true,
                     title,
                     target,
-                    backgroundColor: "black",
                     _dropAction: "alias",
                     _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
                     _width: 60,
@@ -576,8 +577,10 @@ export class CurrentUserUtils {
                 title: "menuItemPanel",
                 childDropAction: "alias",
                 _chromeHidden: true,
+                backgroundColor: Colors.DARK_GRAY,
+                boxShadow: "rgba(0,0,0,0)",
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-                backgroundColor: "black", ignoreClick: true,
+                ignoreClick: true,
                 _gridGap: 0,
                 _yMargin: 0,
                 _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true
@@ -587,8 +590,6 @@ export class CurrentUserUtils {
         PromiseValue(Cast(doc.menuStack, Doc)).then(stack => {
             stack && PromiseValue(stack.data).then(btns => {
                 DocListCastAsync(btns).then(bts => bts?.forEach(btn => {
-                    btn.color = "white";
-                    btn._backgroundColor = "";
                     btn.dontUndo = true;
                     btn.system = true;
                     if (btn.title === "Catalog" || btn.title === "My Files") { // migration from Catalog to My Files
@@ -759,7 +760,7 @@ export class CurrentUserUtils {
         await doc.myDashboards;
         if (doc.myDashboards === undefined) {
             doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "My Dashboards", _height: 400, childHideLinkButton: true,
+                title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
@@ -775,7 +776,7 @@ export class CurrentUserUtils {
         await doc.myPresentations;
         if (doc.myPresentations === undefined) {
             doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "My Presentations", _height: 100,
+                title: "My Trails", _showTitle: "title", _height: 100,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
@@ -794,7 +795,7 @@ export class CurrentUserUtils {
             doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true });
             doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true });
             doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileRoot as Doc, doc.myFileOrphans as Doc], {
-                title: "My Documents", _height: 100,
+                title: "My Documents", _showTitle: "title", _height: 100,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
                 isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
@@ -808,7 +809,7 @@ export class CurrentUserUtils {
         // setup Recently Closed library item
         if (doc.myRecentlyClosedDocs === undefined) {
             doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "Recently Closed", treeViewShowClearButton: true, childHideLinkButton: true,
+                title: "Recently Closed", _showTitle: "title", treeViewShowClearButton: true, childHideLinkButton: true,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
@@ -839,7 +840,7 @@ export class CurrentUserUtils {
             doc.treeViewOpen = true;
             doc.treeViewExpandedView = "fields";
             doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], {
-                treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc",
+                treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
                 _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
             })) as any as Doc;
@@ -859,6 +860,7 @@ export class CurrentUserUtils {
     static async setupSidebarButtons(doc: Doc) {
         CurrentUserUtils.setupSidebarContainer(doc);
         await CurrentUserUtils.setupToolsBtnPanel(doc);
+        CurrentUserUtils.setupImportSidebar(doc);
         CurrentUserUtils.setupDashboards(doc);
         CurrentUserUtils.setupPresentations(doc);
         CurrentUserUtils.setupFilesystem(doc);
@@ -891,6 +893,7 @@ export class CurrentUserUtils {
         (doc["dockedBtn-undo"] as Doc).dontUndo = true;
         (doc["dockedBtn-redo"] as Doc).dontUndo = true;
     }
+
     // sets up the default set of documents to be shown in the Overlay layer
     static setupOverlays(doc: Doc) {
         if (doc.myOverlayDocs === undefined) {
@@ -924,7 +927,8 @@ export class CurrentUserUtils {
             if (!sharedDocs) {
                 sharedDocs = Docs.Create.StackingDocument([], {
                     title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "none", childLimitHeight: 0, _yMargin: 50, _gridGap: 15,
-                    _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, _chromeHidden: true,
+                    _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add,
+                    _chromeHidden: true, boxShadow: "0 0",
                 }, sharingDocumentId + "outer", sharingDocumentId);
                 (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Add;
             }
@@ -939,14 +943,14 @@ export class CurrentUserUtils {
     static setupImportSidebar(doc: Doc) {
         if (doc.myImportDocs === undefined) {
             doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
-                title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
+                title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
                 childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeHidden: true,
             }));
         }
         if (doc.myImportPanel === undefined) {
             const uploads = Cast(doc.myImportDocs, Doc, null);
             const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true });
-            doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true }));
+            doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, _showTitle: "title", ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true, boxShadow: "0 0" }));
         }
     }
 
@@ -1007,10 +1011,14 @@ export class CurrentUserUtils {
                 const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || [];
                 SnappingManager.SetCachedGroups(["Public", ...mygroups?.map(g => StrCast(g.title))]);
             }, { fireImmediately: true });
+        // Document properties on load
         doc.system = true;
+        doc.darkScheme = ColorScheme.Dark;
         doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode;
         doc.title = Doc.CurrentUserEmail;
         doc._raiseWhenDragged = true;
+        doc._showLabel = false;
+        doc._showMenuLabel = true;
         doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)");
         doc.activeInkWidth = StrCast(doc.activeInkWidth, "1");
         doc.activeInkBezier = StrCast(doc.activeInkBezier, "0");
@@ -1201,7 +1209,7 @@ export class CurrentUserUtils {
         const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row");
         Doc.AddDocToList(myPresentations, "data", presentation);
         userDoc.activePresentation = presentation;
-        const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
+        const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`);
         const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
         const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`);
         const createDashboard = ScriptField.MakeScript(`createNewDashboard()`);
@@ -1257,6 +1265,4 @@ Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.
 Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
     "returns all the links to the document or its annotations", "(doc: any)");
 Scripting.addGlobal(function importDocument() { return CurrentUserUtils.importDocument(); },
-    "imports files from device directly into the import sidebar");
-Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; },
-    "toggle between regular rendeing and an informal sketch/comic style");
+    "imports files from device directly into the import sidebar");
\ No newline at end of file
diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss
index b509f9f54..e23bf27c1 100644
--- a/src/client/views/AntimodeMenu.scss
+++ b/src/client/views/AntimodeMenu.scss
@@ -6,6 +6,7 @@
     z-index: 10001;
     height: $antimodemenu-height;
     background: $dark-gray;
+    border-bottom: $standard-border;
     // box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
     // border-radius: 0px 6px 6px 6px;
     z-index: 1001;
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index a5d80cd22..b11aa99b0 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -24,7 +24,7 @@ import { DocumentView } from './nodes/DocumentView';
 import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
 import { TemplateMenu } from "./TemplateMenu";
 import React = require("react");
-import { PresBox } from './nodes/PresBox';
+import { PresBox } from './nodes/trails/PresBox';
 import { undoBatch } from '../util/UndoManager';
 import { CollectionViewType } from './collections/CollectionView';
 const higflyout = require("@hig/flyout");
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 2069986ad..ba1c91720 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -22,10 +22,6 @@
     height: 100%;
 }
 
-.mainContent-div-flyout {
-    left: calc(-1 * var(--flyoutHandleWidth));
-}
-
 // add nodes menu. Note that the + button is actually an input label, not an actual button.
 .mainView-docButtons {
     position: absolute;
@@ -111,14 +107,21 @@
     user-select: none;
 }
 
+.properties-container {
+    height: 100%;
+    position: relative;
+    left: 100%;
+    top: calc(-100% - 36px);
+    z-index: 3000;
+}
+
 .mainView-propertiesDragger {
     //background-color: rgb(140, 139, 139);
-    background-color: $light-gray;
+    background-color: $medium-gray;
     height: 55px;
     width: 17px;
     position: absolute;
     top: 50%;
-    border: 1px black solid;
     border-radius: 0;
     border-top-left-radius: 10px;
     border-bottom-left-radius: 10px;
@@ -141,18 +144,6 @@
     }
 }
 
-.mainiView-propertiesView {
-    display: flex;
-    flex-direction: column;
-    height: 100%;
-    position: absolute;
-    right: 0;
-    top: 0;
-    border-left: solid 1px;
-    z-index: 100000;
-    cursor: auto;
-}
-
 .mainView-innerContent, .mainView-innerContent-dark {
     display: contents;
     flex-direction: row;
@@ -171,7 +162,7 @@
     }
 
     .propertiesView {
-        right: 0;
+        left: 0;
         position: absolute;
         z-index: 2;
         background-color: $medium-gray;
@@ -220,6 +211,7 @@
 .mainView-menuPanel {
     min-width: var(--menuPanelWidth);
     background-color: $dark-gray;
+    border-right: $standard-border;
 
     .collectionStackingView {
         scrollbar-width: none;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7d6bfbd40..49f4f7a6e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -64,6 +64,7 @@ import { PropertiesView } from './PropertiesView';
 import { SearchBox } from './search/SearchBox';
 import { DefaultStyleProvider, DashboardStyleProvider, StyleProp } from './StyleProvider';
 import { TopBar } from './topbar/TopBar';
+import { Colors } from './global/globalEnums';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -179,12 +180,12 @@ export class MainView extends React.Component {
         const targets = document.elementsFromPoint(e.x, e.y);
         if (targets.length) {
             const targClass = targets[0].className.toString();
-            if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) {
-                const check = targets.some((thing) =>
-                    (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" ||
-                        thing.className === "collectionSchema-header-menuOptions"));
-                !check && SearchBox.Instance.resetSearch(true);
-            }
+            // if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) {
+            //     const check = targets.some((thing) =>
+            //         (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" ||
+            //             thing.className === "collectionSchema-header-menuOptions"));
+            //     !check && SearchBox.Instance.resetSearch(true);
+            // }
             !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu();
             !["timeline-menu-desc", "timeline-menu-item", "timeline-menu-input"].includes(targClass) && TimelineMenu.Instance.closeMenu();
         }
@@ -193,7 +194,7 @@ export class MainView extends React.Component {
     initEventListeners = () => {
         window.addEventListener("drop", e => e.preventDefault(), false);  // prevent default behavior of navigating to a new web page
         window.addEventListener("dragover", e => e.preventDefault(), false);
-        document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined));
+        // document.addEventListener("pointermove", action(e => SearchBox.Instance._undoBackground = UndoManager.batchCounter ? "#000000a8" : undefined));
         document.addEventListener("pointerdown", this.globalPointerDown);
         document.addEventListener("click", (e: MouseEvent) => {
             if (!e.cancelBubble) {
@@ -405,22 +406,26 @@ export class MainView extends React.Component {
     }
 
     @computed get mainInnerContent() {
+        const width = this.propertiesWidth() + this._flyoutWidth + this.menuPanelWidth();
+        const transform = this._flyoutWidth ? 'translate(-28px, 0px)' : undefined;
         return <>
             {this.menuPanel}
             <div key="inner" className={`mainView-innerContent${this.darkScheme ? "-dark" : ""}`}>
                 {this.flyout}
-                <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined, left: this._flyoutWidth ? (this._flyoutWidth + this.menuPanelWidth() - 10) : -10 }} onPointerDown={this.onFlyoutPointerDown} >
+                <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
                     <FontAwesomeIcon icon="chevron-left" color={this.darkScheme ? "white" : "black"} style={{ opacity: "50%" }} size="sm" />
                 </div>
-                <div className="mainView-innerContainer" style={{ width: `calc(100% - ${this.propertiesWidth() + this._flyoutWidth + this.menuPanelWidth()}px)` }}>
+                <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)`, transform: transform }}>
                     <CollectionMenu />
 
                     {this.dockingContent}
 
-                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1 }}>
-                        <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.darkScheme ? "white" : "black"} size="sm" />
+                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._flyoutWidth ? 0 : this.propertiesWidth() - 1 }}>
+                        <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.darkScheme ? Colors.WHITE : Colors.BLACK} size="sm" />
+                    </div>
+                    <div className="properties-container">
+                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.getContentsHeight()} />}
                     </div>
-                    {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.getContentsHeight()} />}
                 </div>
             </div>
         </>;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 4df3e4f00..8136edf04 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -24,7 +24,7 @@ import { EditableView } from "./EditableView";
 import { InkStrokeProperties } from "./InkStrokeProperties";
 import { DocumentView, StyleProviderFunc } from "./nodes/DocumentView";
 import { KeyValueBox } from "./nodes/KeyValueBox";
-import { PresBox } from "./nodes/PresBox";
+import { PresBox } from "./nodes/trails/PresBox";
 import { PropertiesButtons } from "./PropertiesButtons";
 import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector";
 import "./PropertiesView.scss";
diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss
index cb59489c0..140be2140 100644
--- a/src/client/views/_nodeModuleOverrides.scss
+++ b/src/client/views/_nodeModuleOverrides.scss
@@ -58,12 +58,10 @@ div .lm_header {
 .lm_header .lm_controls {
     align-items: center;
     position: absolute;
-    background-color: #000000;
+    background-color: $dark-gray;
     border-radius: 5px;
     display: flex;
-    top: 2px;
     justify-content: space-evenly;
-    right: 2px;
     height: 18px;
     width: 65px;
 }
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index c0fc774d3..f04b19ef7 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -38,10 +38,10 @@
         border: unset;
 
         .collectionMenu-divider {
-            height: 85%;
+            height: 100%;
             margin-left: 3px;
             margin-right: 3px;
-            width: 1.5px;
+            width: 2px;
             background-color: $medium-gray;
         }
 
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 6e6fabd0d..a9b978c4e 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -29,7 +29,7 @@ import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocumentView } from "../nodes/DocumentView";
 import { RichTextMenu } from "../nodes/formattedText/RichTextMenu";
-import { PresBox } from "../nodes/PresBox";
+import { PresBox } from "../nodes/trails/PresBox";
 import "./CollectionMenu.scss";
 import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 0e67bebd8..d82810652 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -25,7 +25,7 @@ import { Transform } from '../../util/Transform';
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { LightboxView } from '../LightboxView';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
-import { PresBox, PinProps, PresMovement } from '../nodes/PresBox';
+import { PinProps, PresBox, PresMovement } from '../nodes/trails';
 import { DefaultLayerProvider, DefaultStyleProvider, StyleLayers, StyleProp } from '../StyleProvider';
 import { CollectionDockingView } from './CollectionDockingView';
 import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a4e310e6c..c5f6f7bf2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -38,7 +38,7 @@ import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDo
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from "../../nodes/DocumentView";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
 import { pageSchema } from "../../nodes/ImageBox";
-import { PresBox } from "../../nodes/PresBox";
+import { PresBox } from "../../nodes/trails/PresBox";
 import { StyleLayers, StyleProp } from "../../StyleProvider";
 import { CollectionDockingView } from "../CollectionDockingView";
 import { CollectionSubView } from "../CollectionSubView";
@@ -834,10 +834,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 map(doc => ({ ...this.childDataProvider(doc, ""), ...this.childSizeProvider(doc, "") }));
             if (measuredDocs.length) {
                 const ranges = measuredDocs.reduce(({ xrange, yrange }, { x, y, width, height }) =>  // computes range of content
-                ({
-                    xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) },
-                    yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) }
-                })
+                    ({
+                        xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) },
+                        yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) }
+                    })
                     , {
                         xrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE },
                         yrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b1f2750c3..4fae961b1 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -19,7 +19,8 @@ import { Transform } from "../../../util/Transform";
 import { undoBatch, UndoManager } from "../../../util/UndoManager";
 import { ContextMenu } from "../../ContextMenu";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
-import { PresBox, PresMovement } from "../../nodes/PresBox";
+import { PresBox } from "../../nodes/trails/PresBox";
+import { PresMovement } from "../../nodes/trails/PresEnums";
 import { PreviewCursor } from "../../PreviewCursor";
 import { CollectionDockingView } from "../CollectionDockingView";
 import { SubCollectionViewProps } from "../CollectionSubView";
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index a8d4235bd..72adc171b 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -38,6 +38,9 @@ $antimodemenu-height: 36px;
 $contextMenu-zindex: 100000; // context menu shows up over everything
 $radialMenu-zindex: 100000; // context menu shows up over everything
 
+// borders
+$standard-border: solid 1px #9F9F9F;
+
 $searchpanel-height: 32px;
 $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
 $docDecorations-zindex: 998; // then doc decorations appear over everything else
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 9b75cd8f9..3d2cdf5a4 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -11,7 +11,7 @@ import { CollectionFreeFormView } from "../collections/collectionFreeForm/Collec
 import { CollectionSchemaView } from "../collections/collectionSchema/CollectionSchemaView";
 import { CollectionView } from "../collections/CollectionView";
 import { InkingStroke } from "../InkingStroke";
-import { PresElementBox } from "../presentationview/PresElementBox";
+import { PresElementBox } from "../nodes/trails/PresElementBox";
 import { SearchBox } from "../search/SearchBox";
 import { DashWebRTCVideo } from "../webcam/DashWebRTCVideo";
 import { YoutubeBox } from "./../../apis/youtube/YoutubeBox";
@@ -32,7 +32,7 @@ import { LabelBox } from "./LabelBox";
 import { LinkAnchorBox } from "./LinkAnchorBox";
 import { LinkBox } from "./LinkBox";
 import { PDFBox } from "./PDFBox";
-import { PresBox } from "./PresBox";
+import { PresBox } from "./trails/PresBox";
 import { ScreenshotBox } from "./ScreenshotBox";
 import { ScriptingBox } from "./ScriptingBox";
 import { SliderBox } from "./SliderBox";
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 60fa462ad..80a014926 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -43,7 +43,7 @@ import { DocumentLinksButton } from './DocumentLinksButton';
 import "./DocumentView.scss";
 import { LinkAnchorBox } from './LinkAnchorBox';
 import { LinkDocPreview } from "./LinkDocPreview";
-import { PresBox } from './PresBox';
+import { PresBox } from './trails/PresBox';
 import { RadialMenu } from './RadialMenu';
 import React = require("react");
 import { ScriptingBox } from "./ScriptingBox";
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index 6ae4b9726..0d415e238 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -14,6 +14,7 @@ import { DocComponent } from '../DocComponent';
 import { StyleProp } from '../StyleProvider';
 import { FieldView, FieldViewProps } from './FieldView';
 import './FontIconBox.scss';
+import { Colors } from '../global/globalEnums';
 const FontIconSchema = createSchema({
     icon: "string",
 });
@@ -47,7 +48,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
         const icon = StrCast(this.dataDoc.icon, "user") as any;
         const presSize = shape === 'round' ? 25 : 30;
         const presTrailsIcon = <img src={`/assets/${"presTrails.png"}`}
-            style={{ width: presSize, height: presSize, filter: `invert(${color === "white" ? "100%" : "0%"})`, marginBottom: "5px" }} />;
+            style={{ width: presSize, height: presSize, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})`, marginBottom: "5px" }} />;
         const button = <button className={`menuButton-${shape}`} onContextMenu={this.specificContextMenu}
             style={{ backgroundColor: backgroundColor, }}>
             <div className="menuButton-wrap">
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
deleted file mode 100644
index 5d1c5f4eb..000000000
--- a/src/client/views/nodes/PresBox.scss
+++ /dev/null
@@ -1,1243 +0,0 @@
-@import "../global/globalCssVariables";
-
-.presBox-cont {
-    cursor: auto;
-    position: absolute;
-    display: block;
-    pointer-events: inherit;
-    z-index: 2;
-    font-family: Roboto;
-    width: 100%;
-    min-width: 20px;
-    height: 100%;
-    min-height: 35px;
-    letter-spacing: 2px;
-    overflow: hidden;
-    transition: 0.7s opacity ease;
-
-    .presBox-listCont {
-        position: relative;
-        height: calc(100% - 67px);
-        width: 100%;
-    }
-
-    .presBox-toolbar-dropdown {
-        border-radius: 5px;
-        background-color: white;
-        transform: translate(8px, -5px);
-        box-shadow: 1px 1px 4px 4px rgba(0, 0, 0, 0.25);
-        z-index: 1000;
-        width: calc(100% - 50px);
-        height: max-content;
-        justify-self: center;
-        letter-spacing: normal;
-        height: max-content;
-        font-weight: 500;
-        position: relative;
-        font-size: 13;
-    }
-
-    .presBox-toolbar {
-        position: relative;
-        display: inline-flex;
-        align-items: center;
-        height: 30px;
-        width: 100%;
-        color: $white;
-        background-color: $dark-gray;
-
-        .toolbar-button {
-            cursor: pointer;
-            margin-left: 10px;
-            margin-right: 10px;
-            letter-spacing: 0;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            transition: 0.5s;
-        }
-
-        .toolbar-button.active {
-            color: $light-blue;
-            background-color: white;
-            border-radius: 100%;
-        }
-
-        .toolbar-transitionButtons {
-            display: block;
-
-            .toolbar-transition {
-                display: flex;
-                font-size: 10;
-                width: 100;
-                background-color: rgba(0, 0, 0, 0);
-                min-width: max-content;
-
-                .toolbar-icon {
-                    margin-right: 5px;
-                }
-            }
-        }
-    }
-
-    .toolbar-moreInfo {
-        position: absolute;
-        right: 5px;
-        display: flex;
-        width: max-content;
-        height: 25px;
-        justify-content: center;
-        transform: rotate(90deg);
-        align-items: center;
-        transition: 0.7s ease;
-
-        .toolbar-moreInfoBall {
-            width: 4px;
-            height: 4px;
-            border-radius: 100%;
-            background-color: white;
-            margin: 1px;
-            position: relative;
-        }
-    }
-
-    .toolbar-moreInfo.active {
-        transform: rotate(0deg);
-    }
-
-    .toolbar-divider {
-        border-left: solid $medium-gray 0.5px;
-        height: 20px;
-    }
-}
-
-.dropdown {
-    font-size: 10;
-    margin-left: 5px;
-    color: $medium-gray;
-    transition: 0.5s ease;
-}
-
-.dropdown.active {
-    transform: rotate(180deg);
-    color: $light-blue;
-    opacity: 0.8;
-}
-
-.presBox-radioButtons {
-    font-size: 10px;
-    font-weight: 200;
-    // background-color: rgba(0, 0, 0, 0.1);
-
-    .checkbox-container {
-        margin-left: 10px;
-        display: inline-flex;
-        width: 100%;
-        height: 20px;
-        align-items: center;
-    }
-
-    .checkbox-dropdown {
-        display: flex;
-        width: 100%;
-        align-items: flex-end;
-        gap: 5px;
-
-        .presBox-viewPicker {
-            width: calc(100% - 120px);
-            min-width: 30px;
-        }
-    }
-}
-
-.presBox-ribbon {
-    position: relative;
-    display: inline;
-    font-family: Roboto;
-    z-index: 100;
-    transition: 0.7s;
-
-    .ribbon-doubleButton {
-        display: inline-flex;
-    }
-
-    .presBox-reactiveGrid {
-        display: grid;
-        justify-content: flex-start;
-        align-items: center;
-        grid-template-columns: repeat(auto-fit, 70px);
-    }
-
-    .ribbon-colorBox {
-        cursor: pointer;
-        border: solid 1px $black;
-        display: flex;
-        margin-left: 5px;
-        margin-top: 5px;
-        margin-bottom: 5px;
-        justify-content: center;
-        align-items: center;
-        height: 15px;
-        width: 15px;
-        padding: 0px;
-        transform: translate(2px, 3px);
-    }
-
-    .ribbon-property {
-        font-size: 11;
-        font-weight: 200;
-        height: 20;
-        background-color: $white;
-        color: $black;
-        border: solid 1px $black;
-        display: flex;
-        margin-left: 5px;
-        margin-top: 5px;
-        margin-bottom: 5px;
-        width: max-content;
-        justify-content: center;
-        align-items: center;
-        padding-right: 10px;
-        padding-left: 10px;
-    }
-
-    .ribbon-propertyUpDown {
-        height: 20;
-        width: 20;
-        margin-top: 5px;
-        display: grid;
-        grid-template-rows: 10px 10px;
-
-        .ribbon-propertyUpDownItem {
-            cursor: pointer;
-            color: white;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            height: 100%;
-            width: 100%;
-            background: $black;
-        }
-
-        .ribbon-propertyUpDownItem:hover {
-            background: $medium-gray;
-            transform: scale(1.05);
-        }
-    }
-
-    .presBox-subheading {
-        font-size: 11;
-        font-weight: 400;
-        margin-top: 10px;
-    }
-
-    @media screen and (-webkit-min-device-pixel-ratio:0) {
-
-        .multiThumb-slider {
-            display: grid;
-            background-color: $white;
-            height: 10px;
-            border-radius: 10px;
-            overflow: hidden;
-
-            .toolbar-slider {
-                margin-top: 0px;
-                background: none;
-                -webkit-appearance: none;
-                pointer-events: none;
-            }
-
-            .toolbar-slider.start::-webkit-slider-thumb {
-                width: 10px;
-                pointer-events: auto;
-                -webkit-appearance: none;
-                height: 10px;
-                cursor: ew-resize;
-                background: $medium-blue;
-                box-shadow: -100vw 0 0 100vw $white;
-            }
-
-            .toolbar-slider.end::-webkit-slider-thumb {
-                width: 10px;
-                pointer-events: auto;
-                -webkit-appearance: none;
-                height: 10px;
-                cursor: ew-resize;
-                background: $medium-blue;
-                box-shadow: -100vw 0 0 100vw $light-blue;
-            }
-        }
-
-        .toolbar-slider {
-            margin-top: 5px;
-            position: relative;
-            align-self: center;
-            justify-self: left;
-            overflow: hidden;
-            width: 100%;
-            height: 10px;
-            border-radius: 10px;
-            -webkit-appearance: none;
-            background-color: $white;
-        }
-
-        .toolbar-slider:focus {
-            outline: none;
-        }
-
-        .toolbar-slider::-webkit-slider-runnable-track {
-            height: 10px;
-            -webkit-appearance: none;
-            margin-top: -1px;
-        }
-
-        .toolbar-slider::-webkit-slider-thumb {
-            width: 10px;
-            pointer-events: auto;
-            -webkit-appearance: none;
-            height: 10px;
-            cursor: ew-resize;
-            background: $medium-blue;
-            box-shadow: -100vw 0 0 100vw $light-blue;
-        }
-
-        .presBox-checkbox {
-            -webkit-appearance: none;
-            -webkit-user-select: none;
-            -moz-user-select: none;
-            -ms-user-select: none;
-            user-select: none;
-            margin: 0;
-            margin-right: 3px;
-            border-radius: 100%;
-            height: 15px;
-            width: 15px;
-            min-width: 15px;
-            cursor: pointer;
-            background: $white;
-        }
-
-        .presBox-checkbox:focus {
-            outline: none;
-        }
-
-        .presBox-checkbox:hover {
-            background: $light-gray;
-        }
-
-        .presBox-checkbox:checked {
-            background: $light-blue;
-        }
-    }
-
-
-
-    .slider-headers {
-        position: relative;
-        display: grid;
-        justify-content: space-between;
-        width: 100%;
-        height: max-content;
-        grid-template-columns: auto auto auto;
-        grid-template-rows: max-content;
-        font-weight: 100;
-        margin-top: 3px;
-        font-size: 10px;
-
-        .slider-block {
-            width: 63px;
-            border-radius: 5px;
-            text-align: center;
-            margin-bottom: 8px;
-            margin-top: 8px;
-        }
-
-        .slider-number {
-            border-radius: 3px;
-            width: 30px;
-            margin: auto;
-        }
-    }
-
-    .slider-value {
-        top: -20;
-        color: #2f86a2;
-        position: absolute;
-    }
-
-    .slider-value.none,
-    .slider-headers.none,
-    .toolbar-slider.none {
-        display: none;
-    }
-
-    .dropdown-header {
-        padding-bottom: 10px;
-        font-weight: 800;
-        text-align: center;
-        font-size: 16;
-        width: 90%;
-        color: $black;
-        transform: translate(5%, 0px);
-        border-bottom: solid 2px $medium-gray;
-    }
-
-
-    .ribbon-textInput {
-        border-radius: 2px;
-        height: 20px;
-        font-size: 11.5;
-        font-weight: 100;
-        align-self: center;
-        justify-self: left;
-        margin-top: 5px;
-        padding-left: 10px;
-        background-color: $white;
-        border: solid 1px $black;
-        min-width: 80px;
-        max-width: 200px;
-        width: 100%;
-    }
-
-    .presBox-input {
-        width: 30;
-        height: 100%;
-        background: none;
-        border: none;
-        text-align: right;
-    }
-
-    .presBox-input:focus {
-        outline: none;
-    }
-
-    .ribbon-frameSelector {
-        border: $black solid 1px;
-        width: 60px;
-        height: 20px;
-        margin-top: 5px;
-        display: grid;
-        grid-template-columns: auto 27px auto;
-        position: relative;
-        border-radius: 5px;
-        overflow: hidden;
-        align-items: center;
-        justify-self: left;
-
-        .fwdKeyframe,
-        .backKeyframe {
-            cursor: pointer;
-            position: relative;
-            height: 100%;
-            background: $white;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            text-align: center;
-            color: $black;
-        }
-
-        .numKeyframe {
-            cursor: pointer;
-            font-size: 10;
-            font-weight: 600;
-            position: relative;
-            color: $black;
-            display: flex;
-            width: 100%;
-            height: 100%;
-            text-align: center;
-            align-items: center;
-            justify-content: center;
-        }
-    }
-
-    .ribbon-final-box {
-        align-self: flex-start;
-        justify-self: center;
-        display: grid;
-        margin-top: 10px;
-        grid-template-rows: auto auto;
-        /* padding-left: 10px; */
-        /* padding-right: 10px; */
-        letter-spacing: normal;
-        min-width: max-content;
-        width: 100%;
-        font-size: 13;
-        font-weight: 500;
-        position: relative;
-
-
-        .ribbon-final-button {
-            cursor: pointer;
-            position: relative;
-            font-size: 11;
-            font-weight: normal;
-            letter-spacing: normal;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            margin-bottom: 5px;
-            height: 25px;
-            color: white;
-            width: 100%;
-            max-width: 120;
-            padding-left: 10;
-            padding-right: 10;
-            border-radius: 10px;
-            background-color: $medium-gray;
-        }
-
-        .ribbon-final-button:hover {
-            transform: scale(1.05);
-            transition: all 0.4s;
-        }
-
-        .ribbon-final-button-hidden {
-            cursor: pointer;
-            position: relative;
-            font-size: 11;
-            font-weight: normal;
-            letter-spacing: normal;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            margin-bottom: 5px;
-            height: 25px;
-            color: $light-gray;
-            width: 100%;
-            max-width: 120;
-            padding-left: 10;
-            padding-right: 10;
-            border-radius: 10px;
-            background-color: $black;
-        }
-
-        .ribbon-final-button-hidden:hover {
-            transform: scale(1.05);
-            transition: all 0.4s;
-        }
-
-        .ribbon-frameList {
-            width: calc(100% - 5px);
-            height: 50px;
-            background-color: $white;
-            border: 1px solid $medium-gray;
-            grid-template-rows: max-content;
-
-            .frameList-header {
-                display: grid;
-                width: 100%;
-                height: 20px;
-                background-color: $medium-gray;
-
-                .frameList-headerButtons {
-                    display: flex;
-                    grid-column: 7;
-                    width: 60px;
-                    justify-self: right;
-                    justify-content: flex-end;
-
-                    .headerButton {
-                        cursor: pointer;
-                        position: relative;
-                        border-radius: 100%;
-                        z-index: 300;
-                        width: 15px;
-                        height: 15px;
-                        display: flex;
-                        font-size: 10px;
-                        justify-self: center;
-                        align-self: center;
-                        background-color: rgba(0, 0, 0, 0.5);
-                        color: white;
-                        justify-content: center;
-                        align-items: center;
-                        transition: 0.2s;
-                        margin-right: 3px;
-                    }
-
-                    .headerButton:hover {
-                        background-color: rgba(0, 0, 0, 1);
-                        transform: scale(1.15);
-                    }
-                }
-            }
-        }
-    }
-
-    .selectedList {
-        display: block;
-        min-width: 50;
-        max-width: 120;
-        height: 70;
-        overflow-y: scroll;
-
-        .selectedList-items {
-            font-size: 7;
-            font-weight: normal;
-        }
-    }
-
-    .ribbon-button {
-        cursor: pointer;
-        font-size: 10.5;
-        font-weight: 300;
-        height: 20;
-        background-color: $medium-gray;
-        color: white;
-        display: flex;
-        margin-top: 5px;
-        margin-bottom: 5px;
-        border-radius: 5px;
-        margin-right: 5px;
-        width: max-content;
-        justify-content: center;
-        align-items: center;
-        padding-right: 10px;
-        padding-left: 10px;
-    }
-
-    .ribbon-button:hover {
-        transform: scale(1.03);
-        transition: all 0.4s;
-        font-weight: 400;
-        opacity: 1;
-        color: $white;
-        background-color: $black;
-    }
-
-    .ribbon-toggle {
-        cursor: pointer;
-        font-size: 10.5;
-        font-weight: 200;
-        height: 20;
-        background-color: $white;
-        border: solid 1px rgba(0, 0, 0, 0.5);
-        display: flex;
-        color: $black;
-        margin-top: 5px;
-        margin-bottom: 5px;
-        border-radius: 5px;
-        margin-right: 5px;
-        width: max-content;
-        justify-content: center;
-        align-items: center;
-        padding-right: 10px;
-        padding-left: 10px;
-    }
-
-    .ribbon-toggle.active {
-        background-color: #aedef8;
-    }
-
-    .ribbon-toggle:hover {
-        transform: scale(1.03);
-        transition: all 0.4s;
-        border: solid 1px rgba(0, 0, 0, 0.75);
-    }
-
-    svg.svg-inline--fa.fa-thumbtack.fa-w-12.toolbar-thumbtack {
-        right: 40;
-        position: absolute;
-        transform: rotate(45deg);
-    }
-
-    .ribbon-box {
-        display: grid;
-        grid-template-rows: max-content auto;
-        justify-self: center;
-        margin-top: 10px;
-        padding-right: 10px;
-        letter-spacing: normal;
-        width: 100%;
-        height: max-content;
-        font-weight: 500;
-        position: relative;
-        font-size: 13;
-        padding-bottom: 10px;
-        border-bottom: solid 1px $dark-gray;
-
-        .presBox-dropdown:hover {
-            border: solid 1px $medium-blue;
-
-            .presBox-dropdownIcon {
-                color: $medium-blue;
-            }
-        }
-
-        .presBox-dropdown {
-            cursor: pointer;
-            display: grid;
-            grid-template-columns: auto 20%;
-            position: relative;
-            border: solid 1px $black;
-            background-color: $light-gray;
-            border-radius: 5px;
-            font-size: 10;
-            height: 25;
-            color: $black;
-            padding-left: 5px;
-            align-items: center;
-            margin-top: 5px;
-            margin-bottom: 5px;
-            font-weight: 200;
-            width: 100%;
-            min-width: max-content;
-            max-width: 200px;
-            overflow: visible;
-
-
-            .presBox-dropdownOption {
-                cursor: pointer;
-                font-size: 11;
-                display: block;
-                padding-left: 10px;
-                padding-right: 5px;
-                padding-top: 3;
-                padding-bottom: 3;
-            }
-
-            .presBox-dropdownOption:hover {
-                position: relative;
-                background-color: lightgrey;
-            }
-
-            .presBox-dropdownOption.active {
-                position: relative;
-                background-color: $light-blue;
-            }
-
-            .presBox-dropdownOptions {
-                position: absolute;
-                top: 23px;
-                left: -2px;
-                z-index: 200;
-                width: 85%;
-                min-width: max-content;
-                display: block;
-                background: #FFFFFF;
-                border: 0.5px solid #979797;
-                box-sizing: border-box;
-                box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
-            }
-
-            .presBox-dropdownIcon {
-                position: relative;
-                color: black;
-                align-self: center;
-                justify-self: center;
-                margin-right: 2px;
-            }
-        }
-    }
-}
-
-.presBox-ribbon.active {
-    display: grid;
-    grid-template-columns: auto auto auto auto auto;
-    grid-template-rows: 100%;
-    height: 100px;
-    padding-top: 5px;
-    padding-bottom: 5px;
-    border: solid 1px $black;
-    // overflow: auto; 
-
-    ::-webkit-scrollbar {
-        -webkit-appearance: none;
-        height: 3px;
-        width: 8px;
-    }
-
-    ::-webkit-scrollbar-thumb {
-        border-radius: 2px;
-    }
-}
-
-.dropdown-play-button {
-    cursor: pointer;
-    font-size: 12;
-    padding-left: 5px;
-    padding-right: 5px;
-    padding-top: 5px;
-    padding-bottom: 5px;
-    text-align: left;
-    justify-content: left;
-}
-
-.dropdown-play-button:hover {
-    background-color: lightgrey;
-}
-
-.presBox-button-left {
-    cursor: pointer;
-    position: relative;
-    align-self: flex-start;
-    justify-self: flex-start;
-    width: 100%;
-    height: 100%;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    border-radius: 4px;
-    padding-left: 7px;
-    padding-right: 7px;
-    border-bottom-right-radius: 0;
-    border-top-right-radius: 0;
-}
-
-.presBox-button-right {
-    cursor: pointer;
-    position: relative;
-    text-align: center;
-    border-left: solid 1px $medium-gray;
-    width: 20%;
-    height: 100%;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    border-radius: 4px;
-    padding-left: 7px;
-    padding-right: 7px;
-    border-bottom-left-radius: 0;
-    border-top-left-radius: 0;
-}
-
-.presBox-button-right.active {
-    background-color: #223063;
-    border: #aedcf6 solid 1px;
-    box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
-}
-
-.dropdown-play {
-    cursor: pointer;
-    right: 0px;
-    top: calc(100% + 2px);
-    display: none;
-    border-radius: 5px;
-    width: max-content;
-    min-height: 20px;
-    height: max-content;
-    box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
-    z-index: 200;
-    background-color: white;
-    color: $black;
-    position: absolute;
-    overflow: hidden;
-}
-
-.dropdown-play.active {
-    display: block;
-}
-
-.open-layout {
-    cursor: pointer;
-    position: relative;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    transform: translate(0px, -1px);
-    background-color: $white;
-    width: 40px;
-    height: 15px;
-    align-self: center;
-    justify-self: center;
-    border: solid 1px $black;
-    border-top: 0px;
-    border-bottom-right-radius: 7px;
-    border-bottom-left-radius: 7px;
-}
-
-.layout-container {
-    padding: 5px;
-    display: grid;
-    background-color: $white;
-    grid-template-columns: repeat(auto-fit, minmax(90px, 100px));
-    width: 100%;
-    border: solid 1px $black;
-    min-width: 100px;
-    overflow: hidden;
-
-    .layout:hover {
-        border: solid 2px $medium-blue;
-    }
-
-    .layout {
-        cursor: pointer;
-        align-self: center;
-        justify-self: center;
-        margin-top: 5;
-        margin-bottom: 5;
-        position: relative;
-        height: 55px;
-        min-width: 90px;
-        width: 90px;
-        overflow: hidden;
-        background-color: white;
-        border: solid $medium-gray 1px;
-        display: grid;
-        grid-template-rows: auto;
-        align-items: center;
-        text-align: center;
-
-        .title {
-            position: relative;
-            align-self: end;
-            padding-left: 3px;
-            margin-left: 3px;
-            margin-right: 3px;
-            height: 13;
-            font-size: 12;
-            display: flex;
-            background-color: #white;
-        }
-
-        .subtitle {
-            align-self: flex-start;
-            position: relative;
-            padding-left: 3px;
-            margin-left: 3px;
-            margin-right: 3px;
-            font-weight: 400;
-            height: 13;
-            font-size: 9;
-            display: flex;
-            background-color: $white;
-        }
-
-        .content {
-            position: relative;
-            font-weight: 200;
-            align-self: flex-start;
-            padding-left: 3px;
-            margin-left: 3px;
-            margin-right: 3px;
-            height: 13;
-            font-size: 10;
-            display: flex;
-            background-color: $white;
-            height: 33;
-            text-align: left;
-            font-size: 8px;
-        }
-    }
-}
-
-.presBox-buttons {
-    position: relative;
-    width: 100%;
-    background: gray;
-    min-height: 35px;
-    padding-top: 5px;
-    padding-bottom: 5px;
-    display: grid;
-    grid-template-columns: auto auto;
-
-    .presBox-viewPicker {
-        cursor: pointer;
-        height: 25;
-        position: relative;
-        display: inline-block;
-        grid-column: 1;
-        border-radius: 5px;
-        min-width: 15px;
-        max-width: 100px;
-        left: 8px;
-    }
-
-    .presBox-presentPanel {
-        display: flex;
-        justify-self: end;
-        width: 100%;
-        max-width: 300px;
-        min-width: 150px;
-    }
-
-
-
-    select {
-        background: $dark-gray;
-        color: $white;
-    }
-
-    .presBox-button {
-        cursor: pointer;
-        height: 25px;
-        border-radius: 5px;
-        display: none;
-        justify-content: center;
-        align-content: center;
-        align-items: center;
-        text-align: center;
-        letter-spacing: normal;
-        width: inherit;
-        background: $dark-gray;
-        color: $white;
-    }
-
-    .presBox-button.active {
-        display: flex;
-    }
-
-    .presBox-button.active:hover {
-        background-color: $medium-blue;
-    }
-
-    .presBox-button.edit {
-        display: flex;
-        max-width: 25px;
-    }
-
-    .presBox-button.present {
-        display: flex;
-        width: max-content;
-        position: absolute;
-        right: 10px;
-
-        .present-icon {
-            margin-right: 7px;
-        }
-    }
-
-
-
-    .collectionViewBaseChrome-viewPicker {
-        min-width: 50;
-        width: 5%;
-        height: 25;
-        position: relative;
-        display: inline-block;
-        left: 8px;
-    }
-}
-
-.presBox-backward,
-.presBox-forward {
-    width: 25px;
-    border-radius: 5px;
-    top: 50%;
-    position: absolute;
-    display: inline-block;
-}
-
-.presBox-backward {
-    left: 5;
-}
-
-.presBox-forward {
-    right: 5;
-}
-
-// CSS adjusted for mobile devices
-@media only screen and (max-device-width: 480px) {
-    .presBox-cont .presBox-buttons {
-        position: absolute;
-        top: 70%;
-        left: 50%;
-        transform: translate(-50%, 0);
-        width: max-content;
-        height: 15%;
-        z-index: 2;
-        align-items: center;
-        background: rgba(0, 0, 0, 0);
-        display: inline-flex;
-
-        .presBox-button {
-            margin-top: 5%;
-            height: 250;
-            width: 300;
-            font-size: 100;
-            display: flex;
-            align-items: center;
-            background: $dark-gray;
-            color: $white;
-        }
-
-        .presBox-viewPicker {
-            top: -70;
-            left: 2.5%;
-            height: 50;
-            width: 95%;
-            font-size: 30px;
-            position: absolute;
-            min-width: 50px;
-        }
-    }
-
-    .presBox-cont .presBox-listCont {
-        top: 50;
-        height: calc(100% - 80px);
-    }
-
-    .input,
-    .select {
-        font-size: 100%;
-    }
-}
-
-.miniPres {
-    cursor: grab;
-    position: absolute;
-    right: 10;
-    top: 10;
-    opacity: 0.1;
-    transition: all 0.4s;
-    color: $white;
-}
-
-.miniPres:hover {
-    opacity: 1;
-}
-
-.presPanelOverlay {
-    background-color: $dark-gray;
-    color: $white;
-    border-radius: 5px;
-    grid-template-rows: 100%;
-    height: 25;
-    width: max-content;
-    min-width: max-content;
-    justify-content: space-evenly;
-    align-items: center;
-    display: flex;
-    position: absolute;
-    right: 10px;
-    transition: all 0.2s;
-
-    .presPanel-button-text {
-        cursor: pointer;
-        display: flex;
-        height: 20;
-        width: max-content;
-        font-family: Roboto;
-        font-weight: 400;
-        margin-left: 3px;
-        margin-right: 3px;
-        padding-right: 3px;
-        padding-left: 3px;
-        letter-spacing: normal;
-        border-radius: 5px;
-        align-items: center;
-        justify-content: center;
-        transition: all 0.3s;
-    }
-
-    .presPanel-divider {
-        width: 0.5px;
-        height: 80%;
-        border-right: solid 1px $medium-gray;
-    }
-
-    .presPanel-button-frame {
-        justify-self: center;
-        align-self: center;
-        align-items: center;
-        display: grid;
-        grid-template-columns: auto auto auto;
-        justify-content: space-around;
-        font-size: 11;
-        margin-left: 7;
-        width: 30;
-        height: 85%;
-        background-color: rgba(91, 157, 221, 0.4);
-        border-radius: 5px;
-    }
-
-    .presPanel-button {
-        cursor: pointer;
-        display: flex;
-        height: 20;
-        min-width: 20;
-        margin-left: 3px;
-        margin-right: 3px;
-        border-radius: 100%;
-        align-items: center;
-        justify-content: center;
-        transition: all 0.3s;
-    }
-
-    .presPanel-button:hover {
-        background-color: $medium-gray;
-        transform: scale(1.2);
-    }
-
-    .presPanel-button-text:hover {
-        background-color: $medium-gray;
-    }
-
-
-}
-
-// .miniPres {
-//     cursor: grab;
-//     position: absolute;
-//     overflow: hidden;
-//     right: 10;
-//     top: 10;
-//     opacity: 0.1;
-//     transition: all 0.4s;
-//     /* border: solid 1px; */
-//     color: white;
-//     /* box-shadow: black 0.4vw 0.4vw 0.8vw; */
-
-//     .miniPresOverlay {
-//         display: grid;
-//         grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
-//         grid-template-rows: 100%;
-//         height: 100%;
-//         justify-items: center;
-//         align-items: center;
-
-//         .miniPres-button-text {
-//             cursor: pointer;
-//             display: flex;
-//             height: 20;
-//             font-weight: 400;
-//             min-width: 100%;
-//             border-radius: 5px;
-//             align-items: center;
-//             justify-content: center;
-//             transition: all 0.3s;
-//         }
-
-//         .miniPres-button-frame {
-//             justify-self: center;
-//             align-self: center;
-//             align-items: center;
-//             display: grid;
-//             grid-template-columns: auto auto auto;
-//             justify-content: space-around;
-//             font-size: 11;
-//             margin-left: 7;
-//             width: 30;
-//             height: 85%;
-//             background-color: rgba(91, 157, 221, 0.4);
-//             border-radius: 5px;
-//         }
-
-//         .miniPres-divider {
-//             width: 0.5px;
-//             height: 80%;
-//             border-right: solid 2px #5a5a5a;
-//         }
-
-//         .miniPres-button {
-//             cursor: pointer;
-//             display: flex;
-//             height: 20;
-//             min-width: 20;
-//             border-radius: 100%;
-//             align-items: center;
-//             justify-content: center;
-//             transition: all 0.3s;
-//         }
-
-//         .miniPres-button:hover {
-//             background-color: #5a5a5a;
-//         }
-
-//         .miniPres-button-text:hover {
-//             background-color: #5a5a5a;
-//         }
-//     }
-// }
\ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
deleted file mode 100644
index f3fb6ff17..000000000
--- a/src/client/views/nodes/PresBox.tsx
+++ /dev/null
@@ -1,2472 +0,0 @@
-import React = require("react");
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { ColorState, SketchPicker } from "react-color";
-import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal';
-import { Doc, DocListCast, DocListCastAsync, FieldResult } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { InkTool } from "../../../fields/InkField";
-import { List } from "../../../fields/List";
-import { PrefetchProxy } from "../../../fields/Proxy";
-import { listSpec, makeInterface } from "../../../fields/Schema";
-import { ScriptField } from "../../../fields/ScriptField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { returnFalse, returnOne, returnTrue, emptyFunction } from '../../../Utils';
-import { Docs } from "../../documents/Documents";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { DocumentManager } from "../../util/DocumentManager";
-import { Scripting } from "../../util/Scripting";
-import { SelectionManager } from "../../util/SelectionManager";
-import { undoBatch, UndoManager } from "../../util/UndoManager";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { CollectionView, CollectionViewType } from "../collections/CollectionView";
-import { TabDocView } from "../collections/TabDocView";
-import { ViewBoxBaseComponent } from "../DocComponent";
-import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
-import { FieldView, FieldViewProps } from './FieldView';
-import "./PresBox.scss";
-import Color = require("color");
-import { LightboxView } from "../LightboxView";
-
-export enum PresMovement {
-    Zoom = "zoom",
-    Pan = "pan",
-    Jump = "jump",
-    None = "none",
-}
-
-export enum PresEffect {
-    Zoom = "Zoom",
-    Lightspeed = "Lightspeed",
-    Fade = "Fade in",
-    Flip = "Flip",
-    Rotate = "Rotate",
-    Bounce = "Bounce",
-    Roll = "Roll",
-    None = "None",
-    Left = "left",
-    Right = "right",
-    Center = "center",
-    Top = "top",
-    Bottom = "bottom"
-}
-
-enum PresStatus {
-    Autoplay = "auto",
-    Manual = "manual",
-    Edit = "edit"
-}
-
-export enum PresColor {
-    LightBlue = "#AEDDF8",
-    DarkBlue = "#5B9FDD",
-    LightBackground = "#ececec",
-    SlideBackground = "#d5dce2",
-}
-
-export class PinProps {
-    audioRange?: boolean;
-    unpin?: boolean;
-    setPosition?: boolean;
-    hidePresBox?: boolean;
-}
-
-type PresBoxSchema = makeInterface<[typeof documentSchema]>;
-const PresBoxDocument = makeInterface(documentSchema);
-
-@observer
-export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
-
-    static renderEffectsDoc(renderDoc: any, layoutDoc: Doc) {
-        const effectProps = {
-            left: layoutDoc.presEffectDirection === PresEffect.Left,
-            right: layoutDoc.presEffectDirection === PresEffect.Right,
-            top: layoutDoc.presEffectDirection === PresEffect.Top,
-            bottom: layoutDoc.presEffectDirection === PresEffect.Bottom,
-            opposite: true,
-            delay: layoutDoc.presTransition,
-            // when: this.layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc,
-        };
-        switch (layoutDoc.presEffect) {
-            case PresEffect.Zoom: return (<Zoom {...effectProps}>{renderDoc}</Zoom>);
-            case PresEffect.Fade: return (<Fade {...effectProps}>{renderDoc}</Fade>);
-            case PresEffect.Flip: return (<Flip {...effectProps}>{renderDoc}</Flip>);
-            case PresEffect.Rotate: return (<Rotate {...effectProps}>{renderDoc}</Rotate>);
-            case PresEffect.Bounce: return (<Bounce {...effectProps}>{renderDoc}</Bounce>);
-            case PresEffect.Roll: return (<Roll {...effectProps}>{renderDoc}</Roll>);
-            case PresEffect.Lightspeed: return (<LightSpeed {...effectProps}>{renderDoc}</LightSpeed>);
-            case PresEffect.None:
-            default: return renderDoc;
-        }
-    }
-    public static EffectsProvider(layoutDoc: Doc, renderDoc: any) {
-        return PresBox.Instance && layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc ?
-            PresBox.renderEffectsDoc(renderDoc, layoutDoc)
-            :
-            renderDoc;
-    }
-
-    @observable public static Instance: PresBox;
-
-    @observable _isChildActive = false;
-    @observable _moveOnFromAudio: boolean = true;
-    @observable _presTimer!: NodeJS.Timeout;
-    @observable _presKeyEventsActive: boolean = false;
-
-    @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
-    @observable _eleArray: HTMLElement[] = [];
-    @observable _dragArray: HTMLElement[] = [];
-    @observable _pathBoolean: boolean = false;
-    @observable _expandBoolean: boolean = false;
-
-    private _disposers: { [name: string]: IReactionDisposer } = {};
-    @observable private transitionTools: boolean = false;
-    @observable private newDocumentTools: boolean = false;
-    @observable private progressivizeTools: boolean = false;
-    @observable private openMovementDropdown: boolean = false;
-    @observable private openEffectDropdown: boolean = false;
-    @observable private presentTools: boolean = false;
-    @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
-    @computed get tagDocs() {
-        const tagDocs: Doc[] = [];
-        for (const doc of this.childDocs) {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            tagDocs.push(tagDoc);
-        }
-        return tagDocs;
-    }
-    @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); }
-    @computed get activeItem() { return Cast(this.childDocs[NumCast(this.rootDoc._itemIndex)], Doc, null); }
-    @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); }
-    @computed get scrollable(): boolean {
-        if (this.targetDoc.type === DocumentType.PDF || this.targetDoc.type === DocumentType.WEB || this.targetDoc.type === DocumentType.RTF || this.targetDoc._viewType === CollectionViewType.Stacking) return true;
-        else return false;
-    }
-    @computed get panable(): boolean {
-        if ((this.targetDoc.type === DocumentType.COL && this.targetDoc._viewType === CollectionViewType.Freeform) || this.targetDoc.type === DocumentType.IMG) return true;
-        else return false;
-    }
-    @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); }
-    constructor(props: any) {
-        super(props);
-        if (Doc.UserDoc().activePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this);
-        if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations.
-            Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
-                title: "pres element template", type: DocumentType.PRESELEMENT, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"
-            }));
-            // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement
-            // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent
-            // the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data
-            // stored on each pres element.
-            (this.presElement as Doc).lookupField = ScriptField.MakeFunction("lookupPresBoxField(container, field, data)",
-                { field: "string", data: Doc.name, container: Doc.name });
-        }
-        this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox
-    }
-    @computed get selectedDocumentView() {
-        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
-        if (this._selectedArray.size) return DocumentManager.Instance.getDocumentView(this.rootDoc);
-    }
-    @computed get isPres(): boolean {
-        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
-        if (this.selectedDoc?.type === DocumentType.PRES) {
-            document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
-            document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
-            return true;
-        }
-        return false;
-    }
-    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
-
-    @action
-    componentWillUnmount() {
-        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
-        this._presKeyEventsActive = false;
-        this.resetPresentation();
-        // Turn of progressivize editors
-        this.turnOffEdit(true);
-        Object.values(this._disposers).forEach(disposer => disposer?.());
-    }
-
-    @action
-    componentDidMount() {
-        this.rootDoc.presBox = this.rootDoc;
-        this.rootDoc._forceRenderEngine = "timeline";
-        this.layoutDoc.presStatus = PresStatus.Edit;
-        this.layoutDoc._gridGap = 0;
-        this.layoutDoc._yMargin = 0;
-        this.turnOffEdit(true);
-        DocListCastAsync((Doc.UserDoc().myPresentations as Doc).data).then(pres =>
-            !pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc));
-        this._disposers.selection = reaction(() => SelectionManager.Views(),
-            views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation());
-    }
-
-    @action
-    updateCurrentPresentation = (pres?: Doc) => {
-        if (pres) Doc.UserDoc().activePresentation = pres;
-        else Doc.UserDoc().activePresentation = this.rootDoc;
-        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
-        document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
-        this._presKeyEventsActive = true;
-        PresBox.Instance = this;
-    }
-
-    // There are still other internal frames and should go through all frames before going to next slide
-    nextInternalFrame = (targetDoc: Doc, activeItem: Doc) => {
-        const currentFrame = Cast(targetDoc?._currentFrame, "number", null);
-        const childDocs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
-        targetDoc._viewTransition = "all 1s";
-        setTimeout(() => targetDoc._viewTransition = undefined, 1010);
-        this.nextKeyframe(targetDoc, activeItem);
-        if (activeItem.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, targetDoc);
-        else targetDoc.keyFrameEditing = true;
-    }
-
-    _mediaTimer!: [NodeJS.Timeout, Doc];
-    // 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played
-    startTempMedia = (targetDoc: Doc, activeItem: Doc) => {
-        const duration: number = NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime);
-        if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
-            const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
-            targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.presStartTime), NumCast(activeItem.presStartTime) + duration);
-        }
-        // if (targetDoc.type === DocumentType.AUDIO) {
-        //     if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
-        //     targetDoc._triggerAudio = NumCast(activeItem.presStartTime);
-        //     this._mediaTimer = [setTimeout(() => targetDoc._audioStop = true, duration * 1000), targetDoc];
-        // } else if (targetDoc.type === DocumentType.VID) {
-        //     targetDoc._triggerVideoStop = true;
-        //     setTimeout(() => targetDoc._currentTimecode = NumCast(activeItem.presStartTime), 10);
-        //     setTimeout(() => targetDoc._triggerVideo = true, 20);
-        //     this._mediaTimer = [setTimeout(() => targetDoc._triggerVideoStop = true, (duration * 1000) + 20), targetDoc];
-        // }
-    }
-
-    stopTempMedia = (targetDocField: FieldResult) => {
-        const targetDoc = Cast(targetDocField, Doc, null);
-        if (targetDoc?.type === DocumentType.AUDIO) {
-            if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
-            targetDoc._audioStop = true;
-        } else if (targetDoc?.type === DocumentType.VID) {
-            if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
-            targetDoc._triggerVideoStop = true;
-        }
-    }
-
-    // No more frames in current doc and next slide is defined, therefore move to next slide 
-    nextSlide = (activeNext: Doc) => {
-        const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
-        let nextSelected = this.itemIndex + 1;
-        this.gotoDocument(nextSelected, this.activeItem);
-        for (nextSelected = nextSelected + 1; nextSelected < this.childDocs.length; nextSelected++) {
-            if (!this.childDocs[nextSelected].groupWithUp) {
-                break;
-            } else {
-                console.log("Title: " + this.childDocs[nextSelected].title);
-                this.gotoDocument(nextSelected, this.activeItem, true);
-            }
-        }
-    }
-
-    // Called when the user activates 'next' - to move to the next part of the pres. trail
-    @action
-    next = () => {
-        const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null);
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const lastFrame = Cast(targetDoc?.lastFrame, "number", null);
-        const curFrame = NumCast(targetDoc?._currentFrame);
-        let internalFrames: boolean = false;
-        if (activeItem.presProgressivize || activeItem.zoomProgressivize || targetDoc.scrollProgressivize) internalFrames = true;
-        if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) {
-            // Case 1: There are still other frames and should go through all frames before going to next slide
-            this.nextInternalFrame(targetDoc, activeItem);
-        } else if (this.childDocs[this.itemIndex + 1] !== undefined) {
-            // Case 2: No more frames in current doc and next slide is defined, therefore move to next slide 
-            this.nextSlide(activeNext);
-        } else if (this.childDocs[this.itemIndex + 1] === undefined && (this.layoutDoc.presLoop || this.layoutDoc.presStatus === PresStatus.Edit)) {
-            // Case 3: Last slide and presLoop is toggled ON or it is in Edit mode
-            this.gotoDocument(0, this.activeItem);
-        }
-    }
-
-    // Called when the user activates 'back' - to move to the previous part of the pres. trail
-    @action
-    back = () => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const prevItem = Cast(this.childDocs[Math.max(0, this.itemIndex - 1)], Doc, null);
-        const prevTargetDoc = Cast(prevItem.presentationTargetDoc, Doc, null);
-        const lastFrame = Cast(targetDoc.lastFrame, "number", null);
-        const curFrame = NumCast(targetDoc._currentFrame);
-        let prevSelected = this.itemIndex;
-        // Functionality for group with up
-        let didZoom = activeItem.presMovement;
-        for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) {
-            didZoom = this.childDocs[prevSelected].presMovement;
-        }
-        if (lastFrame !== undefined && curFrame >= 1) {
-            // Case 1: There are still other frames and should go through all frames before going to previous slide
-            this.prevKeyframe(targetDoc, activeItem);
-        } else if (activeItem && this.childDocs[this.itemIndex - 1] !== undefined) {
-            // Case 2: There are no other frames so it should go to the previous slide
-            prevSelected = Math.max(0, prevSelected - 1);
-            this.gotoDocument(prevSelected, activeItem);
-            if (NumCast(prevTargetDoc.lastFrame) > 0) prevTargetDoc._currentFrame = NumCast(prevTargetDoc.lastFrame);
-        } else if (this.childDocs[this.itemIndex - 1] === undefined && this.layoutDoc.presLoop) {
-            // Case 3: Pres loop is on so it should go to the last slide
-            this.gotoDocument(this.childDocs.length - 1, activeItem);
-        }
-    }
-
-    //The function that is called when a document is clicked or reached through next or back.
-    //it'll also execute the necessary actions if presentation is playing.
-    public gotoDocument = action((index: number, from?: Doc, group?: boolean) => {
-        Doc.UnBrushAllDocs();
-        if (index >= 0 && index < this.childDocs.length) {
-            this.rootDoc._itemIndex = index;
-            const activeItem: Doc = this.activeItem;
-            const targetDoc: Doc = this.targetDoc;
-            if (from?.mediaStopTriggerList && this.layoutDoc.presStatus !== PresStatus.Edit) {
-                DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
-            }
-            if (from?.mediaStop === "auto" && this.layoutDoc.presStatus !== PresStatus.Edit) {
-                this.stopTempMedia(from.presentationTargetDoc);
-            }
-            // If next slide is audio / video 'Play automatically' then the next slide should be played
-            if (this.layoutDoc.presStatus !== PresStatus.Edit && (targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && (activeItem.mediaStart === "auto")) {
-                this.startTempMedia(targetDoc, activeItem);
-            }
-            if (targetDoc) {
-                targetDoc && runInAction(() => {
-                    if (activeItem.presMovement === PresMovement.Jump) targetDoc.focusSpeed = 0;
-                    else targetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
-                });
-                setTimeout(() => targetDoc.focusSpeed = 500, this.activeItem.presTransition ? NumCast(this.activeItem.presTransition) + 10 : 510);
-            }
-            if (targetDoc?.lastFrame !== undefined) {
-                targetDoc._currentFrame = 0;
-            }
-            if (!group) this._selectedArray.clear();
-            this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
-            if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
-            this.onHideDocument(); //Handles hide after/before
-        }
-    });
-
-    _navTimer!: NodeJS.Timeout;
-    navigateToView = (targetDoc: Doc, activeItem: Doc) => {
-        clearTimeout(this._navTimer);
-        const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
-        bestTarget && runInAction(() => {
-            if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) {
-                bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
-                bestTarget._scrollTop = activeItem.presPinViewScroll;
-            } else if (bestTarget.type === DocumentType.COMPARISON) {
-                bestTarget._clipWidth = activeItem.presPinClipWidth;
-            } else if (bestTarget.type === DocumentType.VID) {
-                bestTarget._currentTimecode = activeItem.presPinTimecode;
-            } else {
-                bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
-                bestTarget._panX = activeItem.presPinViewX;
-                bestTarget._panY = activeItem.presPinViewY;
-                bestTarget._viewScale = activeItem.presPinViewScale;
-            }
-            this._navTimer = setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510);
-        });
-    }
-
-    /**
-     * This method makes sure that cursor navigates to the element that
-     * has the option open and last in the group. 
-     * Design choice: If the next document is not in presCollection or 
-     * presCollection itself then if there is a presCollection it will add
-     * a new tab. If presCollection is undefined it will open the document
-     * on the right. 
-     */
-    navigateToElement = async (curDoc: Doc) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const srcContext = Cast(targetDoc.context, Doc, null);
-        const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
-        const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
-        const includesDoc: boolean = DocListCast(presCollection?.data).includes(targetDoc);
-        const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === srcContext);
-        this.turnOffEdit();
-        // Handles the setting of presCollection
-        if (includesDoc) {
-            //Case 1: Pres collection should not change as it is already the same
-        } else if (tab !== undefined) {
-            // Case 2: Pres collection should update
-            this.layoutDoc.presCollection = srcContext;
-        }
-        const presStatus = this.rootDoc.presStatus;
-        const selViewCache = Array.from(this._selectedArray.keys());
-        const dragViewCache = Array.from(this._dragArray);
-        const eleViewCache = Array.from(this._eleArray);
-        const self = this;
-        const resetSelection = action(() => {
-            const presDocView = DocumentManager.Instance.getDocumentView(self.rootDoc);
-            if (presDocView) SelectionManager.SelectView(presDocView, false);
-            self.rootDoc.presStatus = presStatus;
-            self._selectedArray.clear();
-            selViewCache.forEach(doc => self._selectedArray.set(doc, undefined));
-            self._dragArray.splice(0, self._dragArray.length, ...dragViewCache);
-            self._eleArray.splice(0, self._eleArray.length, ...eleViewCache);
-        });
-        const openInTab = (doc: Doc, finished?: () => void) => {
-            collectionDocView ? collectionDocView.props.addDocTab(doc, "") : this.props.addDocTab(doc, ":left");
-            this.layoutDoc.presCollection = targetDoc;
-            // this still needs some fixing
-            setTimeout(resetSelection, 500);
-            if (doc !== targetDoc) {
-                setTimeout(finished ?? emptyFunction, 100); /// give it some time to create the targetDoc if we're opening up its context
-            } else {
-                finished?.();
-            }
-        };
-        // If openDocument is selected then it should open the document for the user
-        if (activeItem.openDocument) {
-            LightboxView.SetLightboxDoc(targetDoc);
-        } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
-            LightboxView.SetLightboxDoc(undefined);
-            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right
-        } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
-            LightboxView.SetLightboxDoc(undefined);
-            //awaiting jump so that new scale can be found, since jumping is async     
-            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right    
-        }
-        // After navigating to the document, if it is added as a presPinView then it will
-        // adjust the pan and scale to that of the pinView when it was added.
-        if (activeItem.presPinView) {
-            // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target
-            this.navigateToView(targetDoc, activeItem);
-        }
-        // TODO: Add progressivize for navigating web (storing websites for given frames)
-
-    }
-
-    /**
-     * Uses the viewfinder to progressivize through the different views of a single collection.
-     * @param presTargetDoc: document for which internal zoom is used
-     */
-    zoomProgressivizeNext = (activeItem: Doc) => {
-        const targetDoc: Doc = this.targetDoc;
-        const srcContext = Cast(targetDoc?.context, Doc, null);
-        const docView = DocumentManager.Instance.getDocumentView(targetDoc);
-        const vfLeft = this.checkList(targetDoc, activeItem["viewfinder-left-indexed"]);
-        const vfWidth = this.checkList(targetDoc, activeItem["viewfinder-width-indexed"]);
-        const vfTop = this.checkList(targetDoc, activeItem["viewfinder-top-indexed"]);
-        const vfHeight = this.checkList(targetDoc, activeItem["viewfinder-height-indexed"]);
-        // Case 1: document that is not a Golden Layout tab
-        if (srcContext) {
-            const srcDocView = DocumentManager.Instance.getDocumentView(srcContext);
-            if (srcDocView) {
-                const layoutdoc = Doc.Layout(targetDoc);
-                const panelWidth: number = srcDocView.props.PanelWidth();
-                const panelHeight: number = srcDocView.props.PanelHeight();
-                const newPanX = NumCast(targetDoc.x) + NumCast(layoutdoc._width) / 2;
-                const newPanY = NumCast(targetDoc.y) + NumCast(layoutdoc._height) / 2;
-                const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
-                srcContext._panX = newPanX + (vfLeft + (vfWidth / 2));
-                srcContext._panY = newPanY + (vfTop + (vfHeight / 2));
-                srcContext._viewScale = newScale;
-            }
-        }
-        // Case 2: document is the containing collection
-        if (docView && !srcContext) {
-            const panelWidth: number = docView.props.PanelWidth();
-            const panelHeight: number = docView.props.PanelHeight();
-            const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
-            targetDoc._panX = vfLeft + (vfWidth / 2);
-            targetDoc._panY = vfTop + (vfWidth / 2);
-            targetDoc._viewScale = newScale;
-        }
-        const resize = document.getElementById('resizable');
-        if (resize) {
-            resize.style.width = vfWidth + 'px';
-            resize.style.height = vfHeight + 'px';
-            resize.style.top = vfTop + 'px';
-            resize.style.left = vfLeft + 'px';
-        }
-    }
-
-    /**
-     * For 'Hide Before' and 'Hide After' buttons making sure that
-     * they are hidden each time the presentation is updated.
-     */
-    @action
-    onHideDocument = () => {
-        this.childDocs.forEach((doc, index) => {
-            const curDoc = Cast(doc, Doc, null);
-            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (tagDoc) tagDoc.opacity = 1;
-            const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc);
-            const curInd: number = itemIndexes.indexOf(index);
-            if (tagDoc === this.layoutDoc.presCollection) { tagDoc.opacity = 1; }
-            else {
-                if (itemIndexes.length > 1 && curDoc.presHideBefore && curInd !== 0) { }
-                else if (curDoc.presHideBefore) {
-                    if (index > this.itemIndex) {
-                        tagDoc.opacity = 0;
-                    } else if (!curDoc.presHideAfter) {
-                        tagDoc.opacity = 1;
-                    }
-                }
-                if (itemIndexes.length > 1 && curDoc.presHideAfter && curInd !== (itemIndexes.length - 1)) { }
-                else if (curDoc.presHideAfter) {
-                    if (index < this.itemIndex) {
-                        tagDoc.opacity = 0;
-                    } else if (!curDoc.presHideBefore) {
-                        tagDoc.opacity = 1;
-                    }
-                }
-            }
-        });
-    }
-
-
-
-    //The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc
-    @action
-    startAutoPres = (startSlide: number) => {
-        this.updateCurrentPresentation();
-        let activeItem: Doc = this.activeItem;
-        let targetDoc: Doc = this.targetDoc;
-        let duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
-        const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms));
-        const load = async () => { // Wrap the loop into an async function for this to work
-            for (var i = startSlide; i < this.childDocs.length; i++) {
-                activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-                targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
-                duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
-                if (duration < 100) { duration = 2500; }
-                if (NumCast(targetDoc.lastFrame) > 0) {
-                    for (var f = 0; f < NumCast(targetDoc.lastFrame); f++) {
-                        await timer(duration / NumCast(targetDoc.lastFrame));
-                        this.next();
-                    }
-                }
-
-                await timer(duration); this.next(); // then the created Promise can be awaited
-                if (i === this.childDocs.length - 1) {
-                    setTimeout(() => {
-                        clearTimeout(this._presTimer);
-                        if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = PresStatus.Manual;
-                        else if (this.layoutDoc.presLoop) this.startAutoPres(0);
-                    }, duration);
-                }
-            }
-        };
-        this.layoutDoc.presStatus = PresStatus.Autoplay;
-        this.startPresentation(startSlide);
-        this.gotoDocument(startSlide, activeItem);
-        load();
-    }
-
-    @action
-    pauseAutoPres = () => {
-        if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
-            if (this._presTimer) clearTimeout(this._presTimer);
-            this.layoutDoc.presStatus = PresStatus.Manual;
-            this.layoutDoc.presLoop = false;
-            this.childDocs.forEach(this.stopTempMedia);
-        }
-    }
-
-    //The function that resets the presentation by removing every action done by it. It also
-    //stops the presentaton.
-    resetPresentation = () => {
-        this.rootDoc._itemIndex = 0;
-        this.childDocs.map(doc => Cast(doc.presentationTargetDoc, Doc, null)).filter(doc => doc instanceof Doc).forEach(doc => {
-            try {
-                doc.opacity = 1;
-            } catch (e) {
-                console.log("Reset presentation error: ", e);
-            }
-        });
-    }
-
-    @action togglePath = (srcContext: Doc, off?: boolean) => {
-        if (off) {
-            this._pathBoolean = false;
-            srcContext.presPathView = false;
-        } else {
-            runInAction(() => this._pathBoolean = !this._pathBoolean);
-            srcContext.presPathView = this._pathBoolean;
-        }
-    }
-
-    @action toggleExpandMode = () => {
-        runInAction(() => this._expandBoolean = !this._expandBoolean);
-        this.rootDoc.expandBoolean = this._expandBoolean;
-        this.childDocs.forEach((doc) => {
-            doc.presExpandInlineButton = this._expandBoolean;
-        });
-    }
-
-    /**
-     * The function that starts the presentation at the given index, also checking if actions should be applied
-     * directly at start.
-     * @param startIndex: index that the presentation will start at
-     */
-    startPresentation = (startIndex: number) => {
-        this.updateCurrentPresentation();
-        this.childDocs.map(doc => {
-            const tagDoc = doc.presentationTargetDoc as Doc;
-            if (doc.presHideBefore && this.childDocs.indexOf(doc) > startIndex) {
-                tagDoc.opacity = 0;
-            }
-            if (doc.presHideAfter && this.childDocs.indexOf(doc) < startIndex) {
-                tagDoc.opacity = 0;
-            }
-        });
-    }
-
-    /**
-     * The method called to open the presentation as a minimized view
-     */
-    @action
-    updateMinimize = () => {
-        const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc);
-        if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
-            console.log("case 1");
-            this.layoutDoc.presStatus = PresStatus.Edit;
-            Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
-            CollectionDockingView.AddSplit(this.rootDoc, "right");
-        } else if (this.layoutDoc.context && docView) {
-            console.log("case 2");
-            this.layoutDoc.presStatus = PresStatus.Edit;
-            clearTimeout(this._presTimer);
-            const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250);
-            this.rootDoc.y = pt[1] + 10;
-            this.rootDoc._height = 35;
-            this.rootDoc._width = 250;
-            docView.props.removeDocument?.(this.layoutDoc);
-            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
-        } else {
-            console.log("case 3");
-            // TODO glr: fix this case
-        }
-    }
-
-    /**
-     * Called when the user changes the view type
-     * Either 'List' (stacking) or 'Slides' (carousel)
-     */
-    // @undoBatch
-    viewChanged = action((e: React.ChangeEvent) => {
-        //@ts-ignore
-        const viewType = e.target.selectedOptions[0].value as CollectionViewType;
-        // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here
-        viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined);
-        this.rootDoc._viewType = viewType;
-        if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 0;
-    });
-
-    /**
-     * Called when the user changes the view type
-     * Either 'List' (stacking) or 'Slides' (carousel)
-     */
-    // @undoBatch
-    mediaStopChanged = action((e: React.ChangeEvent) => {
-        const activeItem: Doc = this.activeItem;
-        //@ts-ignore
-        const stopDoc = e.target.selectedOptions[0].value as string;
-        const stopDocIndex: number = Number(stopDoc[0]);
-        activeItem.mediaStopDoc = stopDocIndex;
-        if (this.childDocs[stopDocIndex - 1].mediaStopTriggerList) {
-            const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
-            list.push(activeItem);
-            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
-            console.log(list);
-        } else {
-            this.childDocs[stopDocIndex - 1].mediaStopTriggerList = new List<Doc>();
-            const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
-            list.push(activeItem);
-            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
-            console.log(list);
-        }
-    });
-
-
-    setMovementName = action((movement: any, activeItem: Doc): string => {
-        let output: string = 'none';
-        switch (movement) {
-            case PresMovement.Zoom: output = 'Pan & Zoom'; break; //Pan and zoom
-            case PresMovement.Pan: output = 'Pan'; break; //Pan
-            case PresMovement.Jump: output = 'Jump cut'; break; //Jump Cut
-            case PresMovement.None: output = 'None'; break; //None
-            default: output = 'Zoom'; activeItem.presMovement = 'zoom'; break; //default set as zoom
-        }
-        return output;
-    });
-
-    whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isChildActive = isActive));
-    // For dragging documents into the presentation trail
-    addDocumentFilter = (docs: Doc[]) => {
-        docs.forEach((doc, i) => {
-            if (doc.presentationTargetDoc) return true;
-            if (doc.type === DocumentType.LABEL) {
-                const audio = Cast(doc.annotationOn, Doc, null);
-                if (audio) {
-                    audio.mediaStart = "manual";
-                    audio.mediaStop = "manual";
-                    audio.presStartTime = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
-                    audio.presEndTime = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
-                    audio.presDuration = audio.presStartTime - audio.presEndTime;
-                    TabDocView.PinDoc(audio, { audioRange: true });
-                    setTimeout(() => this.removeDocument(doc), 0);
-                    return false;
-                }
-            } else {
-                if (!doc.aliasOf) {
-                    const original = Doc.MakeAlias(doc);
-                    TabDocView.PinDoc(original);
-                    setTimeout(() => this.removeDocument(doc), 0);
-                    return false;
-                } else {
-                    if (!doc.presentationTargetDoc) doc.title = doc.title + " - Slide";
-                    doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
-                    doc.presMovement = PresMovement.Zoom;
-                    if (this._expandBoolean) doc.presExpandInlineButton = true;
-                }
-            }
-        });
-        return true;
-    }
-    childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement;
-    removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
-    getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
-    panelHeight = () => this.props.PanelHeight() - 40;
-    isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
-        (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
-
-    /**
-     * For sorting the array so that the order is maintained when it is dropped.
-     */
-    @action
-    sortArray = (): Doc[] => {
-        return this.childDocs.filter(doc => this._selectedArray.has(doc));
-    }
-
-    /**
-     * Method to get the list of selected items in the order in which they have been selected
-     */
-    @computed get listOfSelected() {
-        const list = Array.from(this._selectedArray.keys()).map((doc: Doc, index: any) => {
-            const curDoc = Cast(doc, Doc, null);
-            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (curDoc && curDoc === this.activeItem) return <div key={index} className="selectedList-items"><b>{index + 1}.  {curDoc.title}</b></div>;
-            else if (tagDoc) return <div key={index} className="selectedList-items">{index + 1}.  {curDoc.title}</div>;
-            else if (curDoc) return <div key={index} className="selectedList-items">{index + 1}.  {curDoc.title}</div>;
-        });
-        return list;
-    }
-
-    @action
-    selectPres = () => {
-        const presDocView = DocumentManager.Instance.getDocumentView(this.rootDoc);
-        presDocView && SelectionManager.SelectView(presDocView, false);
-    }
-
-    //Regular click
-    @action
-    selectElement = async (doc: Doc) => {
-        const context = Cast(doc.context, Doc, null);
-        this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
-        if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
-        else this.updateCurrentPresentation(context);
-
-        if (this.activeItem.setPosition &&
-            this.activeItem.y !== undefined &&
-            this.activeItem.x !== undefined &&
-            this.targetDoc.x !== undefined &&
-            this.targetDoc.y !== undefined) {
-            const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms));
-            const time = 10;
-            const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y);
-            const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x);
-
-            for (let i = 0; i < time; i++) {
-                this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time;
-                this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time;
-                await timer(0.1);
-            }
-        }
-    }
-
-    //Command click
-    @action
-    multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
-        if (!this._selectedArray.has(doc)) {
-            this._selectedArray.set(doc, undefined);
-            this._eleArray.push(ref);
-            this._dragArray.push(drag);
-        } else {
-            this._selectedArray.delete(doc);
-            this.removeFromArray(this._eleArray, doc);
-            this.removeFromArray(this._dragArray, doc);
-        }
-        this.selectPres();
-    }
-
-    removeFromArray = (arr: any[], val: any) => {
-        const index: number = arr.indexOf(val);
-        const ret: any[] = arr.splice(index, 1);
-        arr = ret;
-    }
-
-    //Shift click
-    @action
-    shiftSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
-        this._selectedArray.clear();
-        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-        if (this.activeItem) {
-            for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) {
-                this._selectedArray.set(this.childDocs[i], undefined);
-                this._eleArray.push(ref);
-                this._dragArray.push(drag);
-            }
-        }
-        this.selectPres();
-    }
-
-    //regular click
-    @action
-    regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean) => {
-        this._selectedArray.clear();
-        this._selectedArray.set(doc, undefined);
-        this._eleArray.splice(0, this._eleArray.length, ref);
-        this._dragArray.splice(0, this._dragArray.length, drag);
-        focus && this.selectElement(doc);
-        this.selectPres();
-    }
-
-    modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => {
-        if (cmdClick) this.multiSelect(doc, ref, drag);
-        else if (shiftClick) this.shiftSelect(doc, ref, drag);
-        else this.regularSelect(doc, ref, drag, focus);
-    }
-
-    static keyEventsWrapper = (e: KeyboardEvent) => {
-        PresBox.Instance.keyEvents(e);
-    }
-
-    // Key for when the presentaiton is active
-    @action
-    keyEvents = (e: KeyboardEvent) => {
-        if (e.target instanceof HTMLInputElement) return;
-        let handled = false;
-        const anchorNode = document.activeElement as HTMLDivElement;
-        if (anchorNode && anchorNode.className?.includes("lm_title")) return;
-        switch (e.key) {
-            case "Backspace":
-                if (this.layoutDoc.presStatus === "edit") {
-                    undoBatch(action(() => {
-                        for (const doc of Array.from(this._selectedArray.keys())) {
-                            this.removeDocument(doc);
-                        }
-                        this._selectedArray.clear();
-                        this._eleArray.length = 0;
-                        this._dragArray.length = 0;
-                    }))();
-                    handled = true;
-                }
-                break;
-            case "Escape":
-                if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { this.updateMinimize(); }
-                else if (this.layoutDoc.presStatus === "edit") { this._selectedArray.clear(); this._eleArray.length = this._dragArray.length = 0; }
-                else this.layoutDoc.presStatus = "edit";
-                if (this._presTimer) clearTimeout(this._presTimer);
-                handled = true;
-                break;
-            case "Down": case "ArrowDown":
-            case "Right": case "ArrowRight":
-                if (e.shiftKey && this.itemIndex < this.childDocs.length - 1) { // TODO: update to work properly
-                    this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) + 1;
-                    this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
-                } else {
-                    this.next();
-                    if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
-                }
-                handled = true;
-                break;
-            case "Up": case "ArrowUp":
-            case "Left": case "ArrowLeft":
-                if (e.shiftKey && this.itemIndex !== 0) { // TODO: update to work properly
-                    this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) - 1;
-                    this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
-                } else {
-                    this.back();
-                    if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
-                }
-                handled = true;
-                break;
-            case "Spacebar": case " ":
-                if (this.layoutDoc.presStatus === PresStatus.Manual) this.startAutoPres(this.itemIndex);
-                else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
-                handled = true;
-                break;
-            case "a":
-                if ((e.metaKey || e.altKey) && this.layoutDoc.presStatus === "edit") {
-                    this._selectedArray.clear();
-                    this.childDocs.forEach(doc => this._selectedArray.set(doc, undefined));
-                    handled = true;
-                }
-            default:
-                break;
-        }
-        if (handled) {
-            e.stopPropagation();
-            e.preventDefault();
-        }
-    }
-
-    /**
-     * 
-     */
-    @action
-    viewPaths = () => {
-        const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
-        if (srcContext) {
-            this.togglePath(srcContext);
-        }
-    }
-
-    getAllIndexes = (arr: Doc[], val: Doc): number[] => {
-        const indexes = [];
-        for (let i = 0; i < arr.length; i++) {
-            arr[i] === val && indexes.push(i);
-        }
-        return indexes;
-    }
-
-    // Adds the index in the pres path graphically
-    @computed get order() {
-        const order: JSX.Element[] = [];
-        const docs: Doc[] = [];
-        const presCollection = Cast(this.rootDoc.presCollection, Doc, null);
-        const dv = DocumentManager.Instance.getDocumentView(presCollection);
-        this.childDocs.filter(doc => Cast(doc.presentationTargetDoc, Doc, null)).forEach((doc, index) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            const srcContext = Cast(tagDoc.context, Doc, null);
-            const width = NumCast(tagDoc._width) / 10;
-            const height = Math.max(NumCast(tagDoc._height) / 10, 15);
-            const edge = Math.max(width, height);
-            const fontSize = edge * 0.8;
-            const gap = 2;
-            if (presCollection === srcContext) {
-                // Case A: Document is contained within the collection
-                if (docs.includes(tagDoc)) {
-                    const prevOccurances: number = this.getAllIndexes(docs, tagDoc).length;
-                    docs.push(tagDoc);
-                    order.push(
-                        <div className="pathOrder"
-                            key={tagDoc.id + 'pres' + index}
-                            style={{ top: NumCast(tagDoc.y) + (prevOccurances * (edge + gap) - (edge / 2)), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
-                            onClick={() => this.selectElement(doc)}>
-                            <div className="pathOrder-frame">{index + 1}</div>
-                        </div>);
-                } else {
-                    docs.push(tagDoc);
-                    order.push(
-                        <div className="pathOrder"
-                            key={tagDoc.id + 'pres' + index}
-                            style={{ top: NumCast(tagDoc.y) - (edge / 2), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
-                            onClick={() => this.selectElement(doc)}>
-                            <div className="pathOrder-frame">{index + 1}</div>
-                        </div>);
-                }
-            } else if (doc.presPinView && presCollection === tagDoc && dv) {
-                // Case B: Document is presPinView and is presCollection
-                const scale: number = 1 / NumCast(doc.presPinViewScale);
-                const height: number = dv.props.PanelHeight() * scale;
-                const width: number = dv.props.PanelWidth() * scale;
-                const indWidth = width / 10;
-                const indHeight = Math.max(height / 10, 15);
-                const indEdge = Math.max(indWidth, indHeight);
-                const indFontSize = indEdge * 0.8;
-                const xLoc: number = NumCast(doc.presPinViewX) - (width / 2);
-                const yLoc: number = NumCast(doc.presPinViewY) - (height / 2);
-                docs.push(tagDoc);
-                order.push(
-                    <>
-                        <div className="pathOrder"
-                            key={tagDoc.id + 'pres' + index}
-                            style={{ top: yLoc - (indEdge / 2), left: xLoc - (indEdge / 2), width: indEdge, height: indEdge, fontSize: indFontSize }}
-                            onClick={() => this.selectElement(doc)}
-                        >
-                            <div className="pathOrder-frame">{index + 1}</div>
-                        </div>
-                        <div className="pathOrder-presPinView" style={{ top: yLoc, left: xLoc, width: width, height: height, borderWidth: indEdge / 10 }}></div>
-                    </>);
-            }
-        });
-        return order;
-    }
-
-    /**
-     * Method called for viewing paths which adds a single line with
-     * points at the center of each document added.
-     * Design choice: When this is called it sets _fitToBox as true so the
-     * user can have an overview of all of the documents in the collection.
-     * (Design needed for when documents in presentation trail are in another
-     * collection)
-     */
-    @computed get paths() {
-        let pathPoints = "";
-        const presCollection = Cast(this.rootDoc.presCollection, Doc, null);
-        this.childDocs.forEach((doc, index) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            const srcContext = Cast(tagDoc?.context, Doc, null);
-            if (tagDoc && presCollection === srcContext) {
-                const n1x = NumCast(tagDoc.x) + (NumCast(tagDoc._width) / 2);
-                const n1y = NumCast(tagDoc.y) + (NumCast(tagDoc._height) / 2);
-                if (index = 0) pathPoints = n1x + "," + n1y;
-                else pathPoints = pathPoints + " " + n1x + "," + n1y;
-            } else if (doc.presPinView && presCollection === tagDoc) {
-                const n1x = NumCast(doc.presPinViewX);
-                const n1y = NumCast(doc.presPinViewY);
-                if (index = 0) pathPoints = n1x + "," + n1y;
-                else pathPoints = pathPoints + " " + n1x + "," + n1y;
-            }
-        });
-        return (<polyline
-            points={pathPoints}
-            style={{
-                opacity: 1,
-                stroke: "#69a6db",
-                strokeWidth: 5,
-                strokeDasharray: '10 5',
-                boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
-            }}
-            fill="none"
-            markerStart="url(#markerArrow)"
-            markerMid="url(#markerSquare)"
-            markerEnd="url(#markerSquareFilled)"
-        />);
-    }
-
-    // Converts seconds to ms and updates presTransition
-    setTransitionTime = (number: String, change?: number) => {
-        let timeInMS = Number(number) * 1000;
-        if (change) timeInMS += change;
-        if (timeInMS < 100) timeInMS = 100;
-        if (timeInMS > 10000) timeInMS = 10000;
-        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presTransition = timeInMS);
-    }
-
-    // Converts seconds to ms and updates presDuration
-    setDurationTime = (number: String, change?: number) => {
-        let timeInMS = Number(number) * 1000;
-        if (change) timeInMS += change;
-        if (timeInMS < 100) timeInMS = 100;
-        if (timeInMS > 20000) timeInMS = 20000;
-        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presDuration = timeInMS);
-    }
-
-    /**
-     * When the movement dropdown is changes
-     */
-    @undoBatch
-    updateMovement = action((movement: any, all?: boolean) => {
-        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
-        array.forEach((doc) => {
-            switch (movement) {
-                case PresMovement.Zoom: //Pan and zoom
-                    doc.presMovement = PresMovement.Zoom;
-                    break;
-                case PresMovement.Pan: //Pan
-                    doc.presMovement = PresMovement.Pan;
-                    break;
-                case PresMovement.Jump: //Jump Cut
-                    doc.presJump = true;
-                    doc.presMovement = PresMovement.Jump;
-                    break;
-                case PresMovement.None: default:
-                    doc.presMovement = PresMovement.None;
-                    break;
-            }
-        });
-    });
-
-    @undoBatch
-    @action
-    updateHideBefore = (activeItem: Doc) => {
-        activeItem.presHideBefore = !activeItem.presHideBefore;
-        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideBefore = activeItem.presHideBefore);
-    }
-
-    @undoBatch
-    @action
-    updateHideAfter = (activeItem: Doc) => {
-        activeItem.presHideAfter = !activeItem.presHideAfter;
-        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideAfter = activeItem.presHideAfter);
-    }
-
-    @undoBatch
-    @action
-    updateOpenDoc = (activeItem: Doc) => {
-        activeItem.openDocument = !activeItem.openDocument;
-        Array.from(this._selectedArray.keys()).forEach((doc) => {
-            doc.openDocument = activeItem.openDocument;
-        });
-    }
-
-    @undoBatch
-    @action
-    updateEffectDirection = (effect: any, all?: boolean) => {
-        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
-        array.forEach((doc) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            switch (effect) {
-                case PresEffect.Left:
-                    tagDoc.presEffectDirection = PresEffect.Left;
-                    break;
-                case PresEffect.Right:
-                    tagDoc.presEffectDirection = PresEffect.Right;
-                    break;
-                case PresEffect.Top:
-                    tagDoc.presEffectDirection = PresEffect.Top;
-                    break;
-                case PresEffect.Bottom:
-                    tagDoc.presEffectDirection = PresEffect.Bottom;
-                    break;
-                case PresEffect.Center: default:
-                    tagDoc.presEffectDirection = PresEffect.Center;
-                    break;
-            }
-        });
-    }
-
-    @undoBatch
-    @action
-    updateEffect = (effect: any, all?: boolean) => {
-        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
-        array.forEach((doc) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            switch (effect) {
-                case PresEffect.Bounce:
-                    tagDoc.presEffect = PresEffect.Bounce;
-                    break;
-                case PresEffect.Fade:
-                    tagDoc.presEffect = PresEffect.Fade;
-                    break;
-                case PresEffect.Flip:
-                    tagDoc.presEffect = PresEffect.Flip;
-                    break;
-                case PresEffect.Roll:
-                    tagDoc.presEffect = PresEffect.Roll;
-                    break;
-                case PresEffect.Rotate:
-                    tagDoc.presEffect = PresEffect.Rotate;
-                    break;
-                case PresEffect.None: default:
-                    tagDoc.presEffect = PresEffect.None;
-                    break;
-            }
-        });
-    }
-
-    _batch: UndoManager.Batch | undefined = undefined;
-
-    @computed get transitionDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const type = targetDoc.type;
-        const isPresCollection: boolean = (targetDoc === this.layoutDoc.presCollection);
-        const isPinWithView: boolean = BoolCast(activeItem.presPinView);
-        if (activeItem && targetDoc) {
-            const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
-            let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
-            if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
-            const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
-            activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
-            return (
-                <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === PresStatus.Edit ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = false; this.openEffectDropdown = false; })}>
-                    <div className="ribbon-box">
-                        Movement
-                        {isPresCollection || (isPresCollection && isPinWithView) ?
-                            <div className="ribbon-property" style={{ marginLeft: 0, height: 25, textAlign: 'left', paddingLeft: 5, paddingRight: 5, fontSize: 10 }}>
-                                {this.scrollable ? "Scroll to pinned view" : !isPinWithView ? "No movement" : "Pan & Zoom to pinned view"}
-                            </div>
-                            :
-                            <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}>
-                                {this.setMovementName(activeItem.presMovement, activeItem)}
-                                <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? PresColor.DarkBlue : 'black' }} icon={"angle-down"} />
-                                <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}>
-                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.None ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.None)}>None</div>
-                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Zoom ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Zoom)}>Pan {"&"} Zoom</div>
-                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Pan ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Pan)}>Pan</div>
-                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Jump ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Jump)}>Jump cut</div>
-                                </div>
-                            </div>
-                        }
-                        <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "inline-flex" : "none" }}>
-                            <div className="presBox-subheading">Movement Speed</div>
-                            <div className="ribbon-property">
-                                <input className="presBox-input"
-                                    type="number" value={transitionSpeed}
-                                    onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
-                            </div>
-                            <div className="ribbon-propertyUpDown">
-                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), 1000))}>
-                                    <FontAwesomeIcon icon={"caret-up"} />
-                                </div>
-                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), -1000))}>
-                                    <FontAwesomeIcon icon={"caret-down"} />
-                                </div>
-                            </div>
-                        </div>
-                        <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed}
-                            className={`toolbar-slider ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}
-                            id="toolbar-slider"
-                            onPointerDown={() => this._batch = UndoManager.StartBatch("presTransition")}
-                            onPointerUp={() => this._batch?.end()}
-                            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                e.stopPropagation();
-                                this.setTransitionTime(e.target.value);
-                            }} />
-                        <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
-                            <div className="slider-text">Fast</div>
-                            <div className="slider-text">Medium</div>
-                            <div className="slider-text">Slow</div>
-                        </div>
-                    </div>
-                    <div className="ribbon-box">
-                        Visibility {"&"} Duration
-                        <div className="ribbon-doubleButton">
-                            {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideBefore ? "active" : ""}`} onClick={() => this.updateHideBefore(activeItem)}>Hide before</div></Tooltip>}
-                            {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideAfter ? "active" : ""}`} onClick={() => this.updateHideAfter(activeItem)}>Hide after</div></Tooltip>}
-                            <Tooltip title={<><div className="dash-tooltip">{"Open in lightbox view"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? PresColor.LightBlue : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Lightbox</div></Tooltip>
-                        </div>
-                        {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <>
-                            <div className="ribbon-doubleButton" >
-                                <div className="presBox-subheading">Slide Duration</div>
-                                <div className="ribbon-property">
-                                    <input className="presBox-input"
-                                        type="number" value={duration}
-                                        onChange={action((e) => this.setDurationTime(e.target.value))} /> s
-                            </div>
-                                <div className="ribbon-propertyUpDown">
-                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
-                                        <FontAwesomeIcon icon={"caret-up"} />
-                                    </div>
-                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), -1000))}>
-                                        <FontAwesomeIcon icon={"caret-down"} />
-                                    </div>
-                                </div>
-                            </div>
-                            <input type="range" step="0.1" min="0.1" max="20" value={duration}
-                                style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }}
-                                className={"toolbar-slider"} id="duration-slider"
-                                onPointerDown={() => { this._batch = UndoManager.StartBatch("presDuration"); }}
-                                onPointerUp={() => { if (this._batch) this._batch.end(); }}
-                                onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }}
-                            />
-                            <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}>
-                                <div className="slider-text">Short</div>
-                                <div className="slider-text">Medium</div>
-                                <div className="slider-text">Long</div>
-                            </div>
-                        </>}
-                    </div>
-                    {isPresCollection ? (null) : <div className="ribbon-box">
-                        Effects
-                        <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown; })} style={{ borderBottomLeftRadius: this.openEffectDropdown ? 0 : 5, border: this.openEffectDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}>
-                            {effect}
-                            <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? PresColor.DarkBlue : 'black' }} icon={"angle-down"} />
-                            <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.None || !targetDoc.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Flip ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Rotate ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Bounce ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
-                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Roll ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
-                            </div>
-                        </div>
-                        <div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
-                            <div className="presBox-subheading" >Effect direction</div>
-                            <div className="ribbon-property">
-                                {this.effectDirection}
-                            </div>
-                        </div>
-                        <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
-                            <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
-                            <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
-                            <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
-                            <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
-                            <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${PresColor.LightBlue}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip>
-                        </div>
-                    </div>}
-                    <div className="ribbon-final-box">
-                        <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}>
-                            Apply to all
-                        </div>
-                    </div>
-                </div >
-            );
-        }
-    }
-
-    @computed get effectDirection(): string {
-        let effect = '';
-        switch (this.targetDoc.presEffectDirection) {
-            case 'left': effect = "Enter from left"; break;
-            case 'right': effect = "Enter from right"; break;
-            case 'top': effect = "Enter from top"; break;
-            case 'bottom': effect = "Enter from bottom"; break;
-            default: effect = "Enter from center"; break;
-        }
-        return effect;
-    }
-
-    @undoBatch
-    @action
-    applyTo = (array: Doc[]) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        this.updateMovement(activeItem.presMovement, true);
-        this.updateEffect(targetDoc.presEffect, true);
-        this.updateEffectDirection(targetDoc.presEffectDirection, true);
-        array.forEach((doc) => {
-            const curDoc = Cast(doc, Doc, null);
-            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (tagDoc && targetDoc) {
-                curDoc.presTransition = activeItem.presTransition;
-                curDoc.presDuration = activeItem.presDuration;
-                curDoc.presHideBefore = activeItem.presHideBefore;
-                curDoc.presHideAfter = activeItem.presHideAfter;
-            }
-        });
-    }
-
-    @computed get presPinViewOptionsDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: "auto", width: 16, filter: 'invert(1)' }} />;
-        return (
-            <>
-                {this.panable || this.scrollable || this.targetDoc.type === DocumentType.COMPARISON ? 'Pinned view' : (null)}
-                <div className="ribbon-doubleButton">
-                    <Tooltip title={<><div className="dash-tooltip">{activeItem.presPinView ? "Turn off pin with view" : "Turn on pin with view"}</div></>}><div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? PresColor.LightBlue : "" }}
-                        onClick={() => {
-                            activeItem.presPinView = !activeItem.presPinView;
-                            targetDoc.presPinView = activeItem.presPinView;
-                            if (activeItem.presPinView) {
-                                if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking) {
-                                    const scroll = targetDoc._scrollTop;
-                                    activeItem.presPinView = true;
-                                    activeItem.presPinViewScroll = scroll;
-                                } else if (targetDoc.type === DocumentType.VID) {
-                                    activeItem.presPinTimecode = targetDoc._currentTimecode;
-                                } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) {
-                                    const x = targetDoc._panX;
-                                    const y = targetDoc._panY;
-                                    const scale = targetDoc._viewScale;
-                                    activeItem.presPinView = true;
-                                    activeItem.presPinViewX = x;
-                                    activeItem.presPinViewY = y;
-                                    activeItem.presPinViewScale = scale;
-                                } else if (targetDoc.type === DocumentType.COMPARISON) {
-                                    const width = targetDoc._clipWidth;
-                                    activeItem.presPinClipWidth = width;
-                                    activeItem.presPinView = true;
-                                }
-                            }
-                        }}>{presPinWithViewIcon}</div></Tooltip>
-                    {activeItem.presPinView ? <Tooltip title={<><div className="dash-tooltip">{"Update the pinned view with the view of the selected document"}</div></>}><div className="ribbon-button"
-                        onClick={() => {
-                            if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
-                                const scroll = targetDoc._scrollTop;
-                                activeItem.presPinViewScroll = scroll;
-                            } else if (targetDoc.type === DocumentType.VID) {
-                                activeItem.presPinTimecode = targetDoc._currentTimecode;
-                            } else if (targetDoc.type === DocumentType.COMPARISON) {
-                                const clipWidth = targetDoc._clipWidth;
-                                activeItem.presPinClipWidth = clipWidth;
-                            } else {
-                                const x = targetDoc._panX;
-                                const y = targetDoc._panY;
-                                const scale = targetDoc._viewScale;
-                                activeItem.presPinViewX = x;
-                                activeItem.presPinViewY = y;
-                                activeItem.presPinViewScale = scale;
-                            }
-                        }}>Update</div></Tooltip> : (null)}
-                </div>
-            </>
-        );
-    }
-
-    @computed get panOptionsDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        return (
-            <>
-                {this.panable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
-                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
-                        <div className="presBox-subheading">Pan X</div>
-                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
-                            <input className="presBox-input"
-                                style={{ textAlign: 'left', width: 50 }}
-                                type="number" value={NumCast(activeItem.presPinViewX)}
-                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewX = Number(val); })} />
-                        </div>
-                    </div>
-                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
-                        <div className="presBox-subheading">Pan Y</div>
-                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
-                            <input className="presBox-input"
-                                style={{ textAlign: 'left', width: 50 }}
-                                type="number" value={NumCast(activeItem.presPinViewY)}
-                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewY = Number(val); })} />
-                        </div>
-                    </div>
-                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
-                        <div className="presBox-subheading">Scale</div>
-                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
-                            <input className="presBox-input"
-                                style={{ textAlign: 'left', width: 50 }}
-                                type="number" value={NumCast(activeItem.presPinViewScale)}
-                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
-                        </div>
-                    </div>
-                </div> : (null)}
-            </>
-        );
-    }
-
-    @computed get scrollOptionsDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        return (
-            <>
-                {this.scrollable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
-                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
-                        <div className="presBox-subheading">Scroll</div>
-                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
-                            <input className="presBox-input"
-                                style={{ textAlign: 'left', width: 50 }}
-                                type="number" value={NumCast(activeItem.presPinViewScroll)}
-                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
-                        </div>
-                    </div>
-                </div> : (null)}
-            </>
-        );
-    }
-
-    @computed get mediaStopSlides() {
-        const activeItem: Doc = this.activeItem;
-        const list = this.childDocs.map((doc, i) => {
-            if (i > this.itemIndex) {
-                return (
-                    <option>{i + 1}. {doc.title}</option>
-                );
-            }
-        });
-        return (
-            list
-        );
-    }
-
-    @computed get mediaOptionsDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const duration = Math.round(NumCast(activeItem[`${Doc.LayoutFieldKey(activeItem)}-duration`]) * 10);
-        const mediaStopDocInd: number = NumCast(activeItem.mediaStopDoc);
-        const mediaStopDocStr: string = mediaStopDocInd ? mediaStopDocInd + ". " + this.childDocs[mediaStopDocInd - 1].title : "";
-        if (activeItem && targetDoc) {
-            return (
-                <div>
-                    <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                        <div>
-                            <div className="ribbon-box">
-                                Start {"&"} End Time
-                                <div className={"slider-headers"}>
-                                    <div className="slider-block" >
-                                        <div className="slider-text" style={{ fontWeight: 500 }}>
-                                            Start time (s)
-                                        </div>
-                                        <div id={"startTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}>
-                                            <input className="presBox-input"
-                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
-                                                type="number" value={NumCast(activeItem.presStartTime)}
-                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
-                                            />
-                                        </div>
-                                    </div>
-                                    <div className="slider-block">
-                                        <div className="slider-text" style={{ fontWeight: 500 }}>
-                                            Duration (s)
-                                        </div>
-                                        <div className="slider-number" style={{ backgroundColor: PresColor.LightBlue }}>
-                                            {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10}
-                                        </div>
-                                    </div>
-                                    <div className="slider-block">
-                                        <div className="slider-text" style={{ fontWeight: 500 }}>
-                                            End time (s)
-                                        </div>
-                                        <div id={"endTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}>
-                                            <input className="presBox-input"
-                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
-                                                type="number" value={NumCast(activeItem.presEndTime)}
-                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
-                                            />
-                                        </div>
-                                    </div>
-                                </div>
-                                <div className="multiThumb-slider">
-                                    <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presEndTime)}
-                                        style={{ gridColumn: 1, gridRow: 1 }}
-                                        className={`toolbar-slider ${"end"}`}
-                                        id="toolbar-slider"
-                                        onPointerDown={() => {
-                                            this._batch = UndoManager.StartBatch("presEndTime");
-                                            const endBlock = document.getElementById("endTime");
-                                            if (endBlock) {
-                                                endBlock.style.color = PresColor.LightBackground;
-                                                endBlock.style.backgroundColor = PresColor.DarkBlue;
-                                            }
-                                        }}
-                                        onPointerUp={() => {
-                                            this._batch?.end();
-                                            const endBlock = document.getElementById("endTime");
-                                            if (endBlock) {
-                                                endBlock.style.color = "black";
-                                                endBlock.style.backgroundColor = PresColor.LightBackground;
-                                            }
-                                        }}
-                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                            e.stopPropagation();
-                                            activeItem.presEndTime = Number(e.target.value);
-                                        }} />
-                                    <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presStartTime)}
-                                        style={{ gridColumn: 1, gridRow: 1 }}
-                                        className={`toolbar-slider ${"start"}`}
-                                        id="toolbar-slider"
-                                        onPointerDown={() => {
-                                            this._batch = UndoManager.StartBatch("presStartTime");
-                                            const startBlock = document.getElementById("startTime");
-                                            if (startBlock) {
-                                                startBlock.style.color = PresColor.LightBackground;
-                                                startBlock.style.backgroundColor = PresColor.DarkBlue;
-                                            }
-                                        }}
-                                        onPointerUp={() => {
-                                            this._batch?.end();
-                                            const startBlock = document.getElementById("startTime");
-                                            if (startBlock) {
-                                                startBlock.style.color = "black";
-                                                startBlock.style.backgroundColor = PresColor.LightBackground;
-                                            }
-                                        }}
-                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                            e.stopPropagation();
-                                            activeItem.presStartTime = Number(e.target.value);
-                                        }} />
-                                </div>
-                                <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
-                                    <div className="slider-text">0 s</div>
-                                    <div className="slider-text"></div>
-                                    <div className="slider-text">{duration / 10} s</div>
-                                </div>
-                            </div>
-                            <div className="ribbon-final-box">
-                                Playback
-                                <div className="presBox-subheading">Start playing:</div>
-                                <div className="presBox-radioButtons">
-                                    <div className="checkbox-container">
-                                        <input className="presBox-checkbox"
-                                            type="checkbox"
-                                            onChange={() => activeItem.mediaStart = "manual"}
-                                            checked={activeItem.mediaStart === "manual"}
-                                        />
-                                        <div>On click</div>
-                                    </div>
-                                    <div className="checkbox-container">
-                                        <input className="presBox-checkbox"
-                                            type="checkbox"
-                                            onChange={() => activeItem.mediaStart = "auto"}
-                                            checked={activeItem.mediaStart === "auto"}
-                                        />
-                                        <div>Automatically</div>
-                                    </div>
-                                </div>
-                                <div className="presBox-subheading">Stop playing:</div>
-                                <div className="presBox-radioButtons">
-                                    <div className="checkbox-container">
-                                        <input className="presBox-checkbox"
-                                            type="checkbox"
-                                            onChange={() => activeItem.mediaStop = "manual"}
-                                            checked={activeItem.mediaStop === "manual"}
-                                        />
-                                        <div>At audio end time</div>
-                                    </div>
-                                    <div className="checkbox-container">
-                                        <input className="presBox-checkbox"
-                                            type="checkbox"
-                                            onChange={() => activeItem.mediaStop = "auto"}
-                                            checked={activeItem.mediaStop === "auto"}
-                                        />
-                                        <div>On slide change</div>
-                                    </div>
-                                    {/* <div className="checkbox-container">
-                                    <input className="presBox-checkbox"
-                                        type="checkbox"
-                                        onChange={() => activeItem.mediaStop = "afterSlide"}
-                                        checked={activeItem.mediaStop === "afterSlide"}
-                                    />
-                                    <div className="checkbox-dropdown">
-                                        After chosen slide
-                                        <select className="presBox-viewPicker"
-                                            style={{ opacity: activeItem.mediaStop === "afterSlide" && this.itemIndex !== this.childDocs.length - 1 ? 1 : 0.3 }}
-                                            onPointerDown={e => e.stopPropagation()}
-                                            onChange={this.mediaStopChanged}
-                                            value={mediaStopDocStr}>
-                                            {this.mediaStopSlides}
-                                        </select>
-                                    </div>
-                                </div> */}
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div >
-            );
-        }
-    }
-
-    @computed get newDocumentToolbarDropdown() {
-        return (
-            <div>
-                <div className={'presBox-toolbar-dropdown'} style={{ display: this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                    <div className="layout-container" style={{ height: 'max-content' }}>
-                        <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} />
-                        <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}>
-                            <div className="title">Title</div>
-                            <div className="subtitle">Subtitle</div>
-                        </div>
-                        <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}>
-                            <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
-                        </div>
-                        <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}>
-                            <div className="title" style={{ alignSelf: 'center' }}>Title</div>
-                            <div className="content">Text goes here</div>
-                        </div>
-                    </div>
-                </div>
-            </div >
-        );
-    }
-
-    @observable openLayouts: boolean = false;
-    @observable addFreeform: boolean = true;
-    @observable layout: string = "";
-    @observable title: string = "";
-
-    @computed get newDocumentDropdown() {
-        return (
-            <div>
-                <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                    <div className="ribbon-box">
-                        Slide Title: <br></br>
-                        <input className="ribbon-textInput" placeholder="..." type="text" name="fname"
-                            onChange={(e) => {
-                                e.stopPropagation();
-                                e.preventDefault();
-                                runInAction(() => this.title = e.target.value);
-                            }}>
-                        </input>
-                    </div>
-                    <div className="ribbon-box">
-                        Choose type:
-                        <div className="ribbon-doubleButton">
-                            <div title="Text" className={'ribbon-toggle'} style={{ background: this.addFreeform ? "" : PresColor.LightBlue }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Text</div>
-                            <div title="Freeform" className={'ribbon-toggle'} style={{ background: this.addFreeform ? PresColor.LightBlue : "" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Freeform</div>
-                        </div>
-                    </div>
-                    <div className="ribbon-box" style={{ display: this.addFreeform ? "grid" : "none" }}>
-                        Preset layouts:
-                        <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}>
-                            <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'blank')} />
-                            <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'title')}>
-                                <div className="title">Title</div>
-                                <div className="subtitle">Subtitle</div>
-                            </div>
-                            <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'header')}>
-                                <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
-                            </div>
-                            <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'content')}>
-                                <div className="title" style={{ alignSelf: 'center' }}>Title</div>
-                                <div className="content">Text goes here</div>
-                            </div>
-                            <div className="layout" style={{ border: this.layout === 'twoColumns' ? `solid 2px ${PresColor.DarkBlue}` : '' }} onClick={action(() => this.layout = 'twoColumns')}>
-                                <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div>
-                                <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div>
-                                <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div>
-                            </div>
-                        </div>
-                        <div className="open-layout" onClick={action(() => this.openLayouts = !this.openLayouts)}>
-                            <FontAwesomeIcon style={{ transition: 'all 0.3s', transform: this.openLayouts ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"caret-down"} size={"lg"} />
-                        </div>
-                    </div>
-                    <div className="ribbon-final-box">
-                        <div className={this.title !== "" && (this.addFreeform && this.layout !== "" || !this.addFreeform) ? "ribbon-final-button-hidden" : "ribbon-final-button"} onClick={() => this.createNewSlide(this.layout, this.title, this.addFreeform)}>
-                            Create New Slide
-                        </div>
-                    </div>
-                </div>
-            </div >
-        );
-    }
-
-    createNewSlide = (layout?: string, title?: string, freeform?: boolean) => {
-        let doc = undefined;
-        if (layout) doc = this.createTemplate(layout);
-        if (freeform && layout) doc = this.createTemplate(layout, title);
-        if (!freeform && !layout) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title });
-        if (doc) {
-            const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
-            const data = Cast(presCollection?.data, listSpec(Doc));
-            const presData = Cast(this.rootDoc.data, listSpec(Doc));
-            if (data && presData) {
-                data.push(doc);
-                TabDocView.PinDoc(doc);
-                this.gotoDocument(this.childDocs.length, this.activeItem);
-            } else {
-                this.props.addDocTab(doc, "add:right");
-            }
-        }
-    }
-
-    createTemplate = (layout: string, input?: string) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        let x = 0;
-        let y = 0;
-        if (activeItem && targetDoc) {
-            x = NumCast(targetDoc.x);
-            y = NumCast(targetDoc.y) + NumCast(targetDoc._height) + 20;
-        }
-        let doc = undefined;
-        const title = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 58, _fontSize: "24pt", });
-        const subtitle = Docs.Create.TextDocument("Click to change subtitle", { title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt" });
-        const header = Docs.Create.TextDocument("Click to change header", { title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt" });
-        const contentTitle = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt" });
-        const content = Docs.Create.TextDocument("Click to change text", { title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" });
-        const content1 = Docs.Create.TextDocument("Click to change text", { title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt" });
-        const content2 = Docs.Create.TextDocument("Click to change text", { title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" });
-        switch (layout) {
-            case 'blank':
-                doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, x: x, y: y });
-                break;
-            case 'title':
-                doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
-                break;
-            case 'header':
-                doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
-                break;
-            case 'content':
-                doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
-                break;
-            case 'twoColumns':
-                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
-                break;
-            default:
-                break;
-        }
-        return doc;
-    }
-
-    // Dropdown that appears when the user wants to begin presenting (either minimize or sidebar view)
-    @computed get presentDropdown() {
-        return (
-            <div className={`dropdown-play ${this.presentTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.updateMinimize(); this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); }))}>
-                    Mini-player
-                </div>
-                <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); }))}>
-                    Sidebar player
-                </div>
-            </div>
-        );
-    }
-
-    // Case in which the document has keyframes to navigate to next key frame
-    @action
-    nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => {
-        const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
-        const currentFrame = Cast(tagDoc._currentFrame, "number", null);
-        if (currentFrame === undefined) {
-            tagDoc._currentFrame = 0;
-            // CollectionFreeFormDocumentView.setupScroll(tagDoc, 0);
-            // CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
-        }
-        // if (tagDoc.editScrollProgressivize) CollectionFreeFormDocumentView.updateScrollframe(tagDoc, currentFrame);
-        CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, tagDoc);
-        tagDoc._currentFrame = Math.max(0, (currentFrame || 0) + 1);
-        tagDoc.lastFrame = Math.max(NumCast(tagDoc._currentFrame), NumCast(tagDoc.lastFrame));
-    }
-
-    @action
-    prevKeyframe = (tagDoc: Doc, actItem: Doc): void => {
-        const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
-        const currentFrame = Cast(tagDoc._currentFrame, "number", null);
-        if (currentFrame === undefined) {
-            tagDoc._currentFrame = 0;
-            // CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
-        }
-        CollectionFreeFormDocumentView.gotoKeyframe(childDocs.slice());
-        tagDoc._currentFrame = Math.max(0, (currentFrame || 0) - 1);
-    }
-
-    /**
-     * Returns the collection type as a string for headers
-     */
-    @computed get stringType(): string {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        let type: string = '';
-        if (activeItem) {
-            switch (targetDoc.type) {
-                case DocumentType.PDF: type = "PDF"; break;
-                case DocumentType.RTF: type = "Text node"; break;
-                case DocumentType.COL: type = "Collection"; break;
-                case DocumentType.AUDIO: type = "Audio"; break;
-                case DocumentType.VID: type = "Video"; break;
-                case DocumentType.IMG: type = "Image"; break;
-                case DocumentType.WEB: type = "Web page"; break;
-                default: type = "Other node"; break;
-            }
-        }
-        return type;
-    }
-
-    @observable private openActiveColorPicker: boolean = false;
-    @observable private openViewedColorPicker: boolean = false;
-
-
-
-    @computed get progressivizeDropdown() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        if (activeItem && targetDoc) {
-            const activeFontColor = targetDoc["pres-text-color"] ? StrCast(targetDoc["pres-text-color"]) : "Black";
-            const viewedFontColor = targetDoc["pres-text-viewed-color"] ? StrCast(targetDoc["pres-text-viewed-color"]) : "Black";
-            return (
-                <div>
-                    <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                        <div className="ribbon-box">
-                            {this.stringType} selected
-                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
-                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeChild}>Contents</div>
-                                <div className="ribbon-toggle" style={{ opacity: activeItem.presProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editProgressivize ? PresColor.LightBlue : "" }} onClick={this.editProgressivize}>Edit</div>
-                            </div>
-                            <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}>
-                                <div className="presBox-subheading">Active text color</div>
-                                <div className="ribbon-colorBox" style={{ backgroundColor: activeFontColor, height: 15, width: 15 }} onClick={action(() => { this.openActiveColorPicker = !this.openActiveColorPicker; })}>
-                                </div>
-                            </div>
-                            {this.activeColorPicker}
-                            <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}>
-                                <div className="presBox-subheading">Viewed font color</div>
-                                <div className="ribbon-colorBox" style={{ backgroundColor: viewedFontColor, height: 15, width: 15 }} onClick={action(() => this.openViewedColorPicker = !this.openViewedColorPicker)}>
-                                </div>
-                            </div>
-                            {this.viewedColorPicker}
-                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}>
-                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.zoomProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeZoom}>Zoom</div>
-                                <div className="ribbon-toggle" style={{ opacity: activeItem.zoomProgressivize ? 1 : 0.4, backgroundColor: activeItem.editZoomProgressivize ? PresColor.LightBlue : "" }} onClick={this.editZoomProgressivize}>Edit</div>
-                            </div>
-                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: targetDoc._viewType === "stacking" || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
-                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.scrollProgressivize ? PresColor.LightBlue : "" }} onClick={this.progressivizeScroll}>Scroll</div>
-                                <div className="ribbon-toggle" style={{ opacity: activeItem.scrollProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editScrollProgressivize ? PresColor.LightBlue : "" }} onClick={this.editScrollProgressivize}>Edit</div>
-                            </div>
-                        </div>
-                        <div className="ribbon-final-box">
-                            Frames
-                            <div className="ribbon-doubleButton">
-                                <div className="ribbon-frameSelector">
-                                    <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc, activeItem); }}>
-                                        <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
-                                    </div>
-                                    <div key="num" title="toggle view all" className="numKeyframe" style={{ color: targetDoc.keyFrameEditing ? "white" : "black", backgroundColor: targetDoc.keyFrameEditing ? PresColor.DarkBlue : PresColor.LightBlue }}
-                                        onClick={action(() => targetDoc.keyFrameEditing = !targetDoc.keyFrameEditing)} >
-                                        {NumCast(targetDoc._currentFrame)}
-                                    </div>
-                                    <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={e => { e.stopPropagation(); this.nextKeyframe(targetDoc, activeItem); }}>
-                                        <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
-                                    </div>
-                                </div>
-                                <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div className="ribbon-property">{NumCast(targetDoc.lastFrame)}</div></Tooltip>
-                            </div>
-                            <div className="ribbon-frameList">
-                                {this.frameListHeader}
-                                {this.frameList}
-                            </div>
-                            <div className="ribbon-toggle" style={{ height: 20, backgroundColor: PresColor.LightBlue }} onClick={() => console.log(" TODO: play frames")}>Play</div>
-                        </div>
-                    </div>
-                </div>
-            );
-        }
-    }
-
-    @undoBatch
-    @action
-    switchActive = (color: ColorState) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const val = String(color.hex);
-        targetDoc["pres-text-color"] = val;
-        return true;
-    }
-    @undoBatch
-    @action
-    switchPresented = (color: ColorState) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const val = String(color.hex);
-        targetDoc["pres-text-viewed-color"] = val;
-        return true;
-    }
-
-    @computed get activeColorPicker() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        return !this.openActiveColorPicker ? (null) : <SketchPicker onChange={this.switchActive}
-            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-                '#FFFFFF', '#f1efeb', 'transparent']}
-            color={StrCast(targetDoc["pres-text-color"])} />;
-    }
-
-    @computed get viewedColorPicker() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        return !this.openViewedColorPicker ? (null) : <SketchPicker onChange={this.switchPresented}
-            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-                '#FFFFFF', '#f1efeb', 'transparent']}
-            color={StrCast(targetDoc["pres-text-viewed-color"])} />;
-    }
-
-    @action
-    turnOffEdit = (paths?: boolean) => {
-        // Turn off paths
-        if (paths) {
-            const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
-            if (srcContext) this.togglePath(srcContext, true);
-        }
-        // Turn off the progressivize editors for each document
-        this.childDocs.forEach((doc) => {
-            doc.editSnapZoomProgressivize = false;
-            doc.editZoomProgressivize = false;
-            const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            if (targetDoc) {
-                targetDoc.editZoomProgressivize = false;
-                // targetDoc.editScrollProgressivize = false;
-            }
-        });
-    }
-
-    //Toggle whether the user edits or not
-    @action
-    editZoomProgressivize = (e: React.MouseEvent) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        if (!targetDoc.editZoomProgressivize) {
-            if (!activeItem.zoomProgressivize) activeItem.zoomProgressivize = true; targetDoc.zoomProgressivize = true;
-            targetDoc.editZoomProgressivize = true;
-            activeItem.editZoomProgressivize = true;
-        } else {
-            targetDoc.editZoomProgressivize = false;
-            activeItem.editZoomProgressivize = false;
-        }
-    }
-
-    //Toggle whether the user edits or not
-    @action
-    editScrollProgressivize = (e: React.MouseEvent) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        if (!targetDoc.editScrollProgressivize) {
-            if (!targetDoc.scrollProgressivize) { targetDoc.scrollProgressivize = true; activeItem.scrollProgressivize = true; }
-            targetDoc.editScrollProgressivize = true;
-        } else {
-            targetDoc.editScrollProgressivize = false;
-        }
-    }
-
-    //Progressivize Zoom
-    @action
-    progressivizeScroll = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        const activeItem: Doc = this.activeItem;
-        activeItem.scrollProgressivize = !activeItem.scrollProgressivize;
-        const targetDoc: Doc = this.targetDoc;
-        targetDoc.scrollProgressivize = !targetDoc.scrollProgressivize;
-        // CollectionFreeFormDocumentView.setupScroll(targetDoc, NumCast(targetDoc._currentFrame));
-        if (targetDoc.editScrollProgressivize) {
-            targetDoc.editScrollProgressivize = false;
-            targetDoc._currentFrame = 0;
-            targetDoc.lastFrame = 0;
-        }
-    }
-
-    //Progressivize Zoom
-    @action
-    progressivizeZoom = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        const activeItem: Doc = this.activeItem;
-        activeItem.zoomProgressivize = !activeItem.zoomProgressivize;
-        const targetDoc: Doc = this.targetDoc;
-        targetDoc.zoomProgressivize = !targetDoc.zoomProgressivize;
-        CollectionFreeFormDocumentView.setupZoom(activeItem, targetDoc);
-        if (activeItem.editZoomProgressivize) {
-            activeItem.editZoomProgressivize = false;
-            targetDoc._currentFrame = 0;
-            targetDoc.lastFrame = 0;
-        }
-    }
-
-    //Progressivize Child Docs
-    @action
-    editProgressivize = (e: React.MouseEvent) => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        targetDoc._currentFrame = targetDoc.lastFrame;
-        if (!targetDoc.editProgressivize) {
-            if (!activeItem.presProgressivize) { activeItem.presProgressivize = true; targetDoc.presProgressivize = true; }
-            targetDoc.editProgressivize = true;
-        } else {
-            targetDoc.editProgressivize = false;
-        }
-    }
-
-    @action
-    progressivizeChild = (e: React.MouseEvent) => {
-        e.stopPropagation();
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
-        if (!activeItem.presProgressivize) {
-            targetDoc.keyFrameEditing = false;
-            activeItem.presProgressivize = true;
-            targetDoc.presProgressivize = true;
-            targetDoc._currentFrame = 0;
-            docs.forEach((doc, i) => CollectionFreeFormDocumentView.setupKeyframes([doc], i, true));
-            targetDoc.lastFrame = targetDoc.lastFrame ? NumCast(targetDoc.lastFrame) : docs.length - 1;
-        } else {
-            // targetDoc.editProgressivize = false;
-            activeItem.presProgressivize = false;
-            targetDoc.presProgressivize = false;
-            targetDoc._currentFrame = 0;
-            targetDoc.keyFrameEditing = true;
-        }
-    }
-
-    @action
-    checkMovementLists = (doc: Doc, xlist: any, ylist: any) => {
-        const x: List<number> = xlist;
-        const y: List<number> = ylist;
-        const tags: JSX.Element[] = [];
-        let pathPoints = ""; //List of all of the pathpoints that need to be added
-        for (let i = 0; i < x.length - 1; i++) {
-            if (y[i] || x[i]) {
-                if (i === 0) pathPoints = (x[i] - 11) + "," + (y[i] + 33);
-                else pathPoints = pathPoints + " " + (x[i] - 11) + "," + (y[i] + 33);
-                tags.push(<div className="progressivizeMove-frame" style={{ position: 'absolute', top: y[i], left: x[i] }}>{i}</div>);
-            }
-        }
-        tags.push(<svg style={{ overflow: 'visible', position: 'absolute' }}><polyline
-            points={pathPoints}
-            style={{
-                position: 'absolute',
-                opacity: 1,
-                stroke: "#000000",
-                strokeWidth: 2,
-                strokeDasharray: '10 5',
-            }}
-            fill="none"
-        /></svg>);
-        return tags;
-    }
-
-    @observable
-    toggleDisplayMovement = (doc: Doc) => {
-        if (doc.displayMovement) doc.displayMovement = false;
-        else doc.displayMovement = true;
-    }
-
-    @action
-    checkList = (doc: Doc, list: any): number => {
-        const x: List<number> = list;
-        if (x && x.length >= NumCast(doc._currentFrame) + 1) {
-            return x[NumCast(doc._currentFrame)];
-        } else if (x) {
-            x.length = NumCast(doc._currentFrame) + 1;
-            x[NumCast(doc._currentFrame)] = x[NumCast(doc._currentFrame) - 1];
-            return x[NumCast(doc._currentFrame)];
-        } else return 100;
-    }
-
-    @computed get progressivizeChildDocs() {
-        const targetDoc: Doc = this.targetDoc;
-        const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
-        const tags: JSX.Element[] = [];
-        docs.forEach((doc, index) => {
-            if (doc["x-indexed"] && doc["y-indexed"]) {
-                tags.push(<div style={{ position: 'absolute', display: doc.displayMovement ? "block" : "none" }}>{this.checkMovementLists(doc, doc["x-indexed"], doc["y-indexed"])}</div>);
-            }
-            tags.push(
-                <div className="progressivizeButton" key={index} onPointerLeave={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? PresColor.LightBlue : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}>
-                    <div className="progressivizeButton-prev"><FontAwesomeIcon icon={"caret-left"} size={"lg"} onClick={e => { e.stopPropagation(); this.prevAppearFrame(doc, index); }} /></div>
-                    <div className="progressivizeButton-frame">{doc.appearFrame}</div>
-                    <div className="progressivizeButton-next"><FontAwesomeIcon icon={"caret-right"} size={"lg"} onClick={e => { e.stopPropagation(); this.nextAppearFrame(doc, index); }} /></div>
-                </div>);
-        });
-        return tags;
-    }
-
-    @action
-    nextAppearFrame = (doc: Doc, i: number): void => {
-        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-        // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
-        const appearFrame = Cast(doc.appearFrame, "number", null);
-        if (appearFrame === undefined) {
-            doc.appearFrame = 0;
-        }
-        doc.appearFrame = appearFrame + 1;
-        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
-    }
-
-    @action
-    prevAppearFrame = (doc: Doc, i: number): void => {
-        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-        // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
-        const appearFrame = Cast(doc.appearFrame, "number", null);
-        if (appearFrame === undefined) {
-            doc.appearFrame = 0;
-        }
-        doc.appearFrame = Math.max(0, appearFrame - 1);
-        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
-    }
-
-    @action
-    updateOpacityList = (list: any, frame: number) => {
-        const x: List<number> = list;
-        if (x && x.length >= frame) {
-            for (let i = 0; i < x.length; i++) {
-                if (i < frame) {
-                    x[i] = 0;
-                } else if (i >= frame) {
-                    x[i] = 1;
-                }
-            }
-            list = x;
-        } else {
-            x.length = frame + 1;
-            for (let i = 0; i < x.length; i++) {
-                if (i < frame) {
-                    x[i] = 0;
-                } else if (i >= frame) {
-                    x[i] = 1;
-                }
-            }
-            list = x;
-        }
-    }
-
-    @computed get moreInfoDropdown() {
-        return (<div></div>);
-    }
-
-    @computed
-    get toolbarWidth(): number {
-        const width = this.props.PanelWidth();
-        return width;
-    }
-
-    @action
-    toggleProperties = () => {
-        if (CurrentUserUtils.propertiesWidth > 0) {
-            CurrentUserUtils.propertiesWidth = 0;
-        } else {
-            CurrentUserUtils.propertiesWidth = 250;
-        }
-    }
-
-    @computed get toolbar() {
-        const propIcon = CurrentUserUtils.propertiesWidth > 0 ? "angle-double-right" : "angle-double-left";
-        const propTitle = CurrentUserUtils.propertiesWidth > 0 ? "Close Presentation Panel" : "Open Presentation Panel";
-        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
-        const isMini: boolean = this.toolbarWidth <= 100;
-        const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
-        return (mode === CollectionViewType.Carousel3D) ? (null) : (
-            <div id="toolbarContainer" className={'presBox-toolbar'}>
-                {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
-                    <FontAwesomeIcon icon={"plus"} />
-                    <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
-                </div></Tooltip> */}
-                <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}>
-                    <div style={{ opacity: this.childDocs.length > 1 && this.layoutDoc.presCollection ? 1 : 0.3, color: this._pathBoolean ? PresColor.DarkBlue : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 && this.layoutDoc.presCollection ? this.viewPaths : undefined}>
-                        <FontAwesomeIcon icon={"exchange-alt"} />
-                    </div>
-                </Tooltip>
-                {isMini ? (null) :
-                    <>
-                        <div className="toolbar-divider" />
-                        {/* <Tooltip title={<><div className="dash-tooltip">{this._expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
-                            <div className={"toolbar-button"}
-                                style={{ color: this._expandBoolean ? PresColors.DarkBlue : 'white' }}
-                                onClick={this.toggleExpandMode}>
-                                <FontAwesomeIcon icon={"eye"} />
-                            </div>
-                        </Tooltip>
-                        <div className="toolbar-divider" /> */}
-                        <Tooltip title={<><div className="dash-tooltip">{presKeyEvents ? "Keys are active" : "Keys are not active - click anywhere on the presentation trail to activate keys"}</div></>}>
-                            <div className="toolbar-button" style={{ cursor: presKeyEvents ? 'default' : 'pointer', position: 'absolute', right: 30, fontSize: 16 }}>
-                                <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"keyboard"} style={{ color: presKeyEvents ? PresColor.DarkBlue : 'white' }} />
-                            </div>
-                        </Tooltip>
-                        <Tooltip title={<><div className="dash-tooltip">{propTitle}</div></>}>
-                            <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
-                                <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? PresColor.DarkBlue : 'white' }} />
-                            </div>
-                        </Tooltip>
-                    </>
-                }
-            </div>
-        );
-    }
-
-    /**
-     * Top panel containes:
-     * viewPicker: The option to choose between List and Slides view for the presentaiton trail
-     * presentPanel: The button to start the presentation / open minimized view of the presentation
-     */
-    @computed get topPanel() {
-        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
-        const isMini: boolean = this.toolbarWidth <= 100;
-        return (
-            <div className="presBox-buttons" style={{ display: !this.rootDoc._chromeHidden ? "none" : undefined }}>
-                {isMini ? (null) : <select className="presBox-viewPicker"
-                    style={{ display: this.layoutDoc.presStatus === "edit" ? "block" : "none" }}
-                    onPointerDown={e => e.stopPropagation()}
-                    onChange={this.viewChanged}
-                    value={mode}>
-                    <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option>
-                    <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel3D}>3D Carousel</option>
-                </select>}
-                <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}>
-                    <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}>
-                        <div className="presBox-button-left"
-                            onClick={undoBatch(() => {
-                                if (this.childDocs.length) {
-                                    this.layoutDoc.presStatus = "manual";
-                                    this.gotoDocument(this.itemIndex, this.activeItem);
-                                }
-                            })}>
-                            <FontAwesomeIcon icon={"play-circle"} />
-                            <div style={{ display: this.props.PanelWidth() > 200 ? "inline-flex" : "none" }}>&nbsp; Present</div>
-                        </div>
-                        {(mode === CollectionViewType.Carousel3D || isMini) ? (null) : <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`}
-                            onClick={(action(() => {
-                                if (this.childDocs.length) this.presentTools = !this.presentTools;
-                            }))}>
-                            <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
-                            {this.presentDropdown}
-                        </div>}
-                    </span>
-                    {this.playButtons}
-                </div>
-            </div>
-        );
-    }
-
-    @action
-    getList = (list: any): List<number> => {
-        const x: List<number> = list;
-        return x;
-    }
-
-    @action
-    updateList = (list: any): List<number> => {
-        const targetDoc: Doc = this.targetDoc;
-        const x: List<number> = list;
-        x.length + 1;
-        x[x.length - 1] = NumCast(targetDoc._scrollY);
-        return x;
-    }
-
-    @action
-    newFrame = () => {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const type: string = StrCast(targetDoc.type);
-        if (!activeItem.frameList) activeItem.frameList = new List<number>();
-        switch (type) {
-            case (DocumentType.PDF || DocumentType.RTF || DocumentType.WEB):
-                this.updateList(activeItem.frameList);
-                break;
-            case DocumentType.COL:
-                break;
-            default:
-                break;
-        }
-    }
-
-    @computed get frameListHeader() {
-        return (<div className="frameList-header">
-            &nbsp; Frames {this.panable ? <i>Panable</i> : this.scrollable ? <i>Scrollable</i> : (null)}
-            <div className={"frameList-headerButtons"}>
-                <Tooltip title={<><div className="dash-tooltip">{"Add frame by example"}</div></>}><div className={"headerButton"} onClick={e => { e.stopPropagation(); this.newFrame(); }}>
-                    <FontAwesomeIcon icon={"plus"} onPointerDown={e => e.stopPropagation()} />
-                </div></Tooltip>
-                <Tooltip title={<><div className="dash-tooltip">{"Edit in collection"}</div></>}><div className={"headerButton"} onClick={e => { e.stopPropagation(); console.log('New frame'); }}>
-                    <FontAwesomeIcon icon={"edit"} onPointerDown={e => e.stopPropagation()} />
-                </div></Tooltip>
-            </div>
-        </div>);
-    }
-
-    @computed get frameList() {
-        const activeItem: Doc = this.activeItem;
-        const targetDoc: Doc = this.targetDoc;
-        const frameList: List<number> = this.getList(activeItem.frameList);
-        if (frameList) {
-            const frameItems = frameList.map((value) =>
-                <div className="framList-item">
-
-                </div>
-            );
-            return (
-
-                <div className="frameList-container">
-                    {frameItems}
-                </div>
-            );
-        } else return (null);
-
-    }
-
-    @computed get playButtonFrames() {
-        const targetDoc: Doc = this.targetDoc;
-        return (
-            <>
-                {this.targetDoc ? <div className="presPanel-button-frame" style={{ display: targetDoc.lastFrame !== undefined && targetDoc.lastFrame >= 0 ? "inline-flex" : "none" }}>
-                    <div>{targetDoc._currentFrame}</div>
-                    <div className="presPanel-divider" style={{ border: 'solid 0.5px white', height: '60%' }}></div>
-                    <div>{targetDoc.lastFrame}</div>
-                </div> : null}
-            </>
-        );
-    }
-
-    @computed get playButtons() {
-        const presEnd: boolean = !this.layoutDoc.presLoop && (this.itemIndex === this.childDocs.length - 1);
-        const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0);
-        // Case 1: There are still other frames and should go through all frames before going to next slide
-        return (<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}>
-            <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? PresColor.DarkBlue : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
-            <div className="presPanel-divider"></div>
-            <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
-            <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? "pause" : "play"} /></div></Tooltip>
-            <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
-            <div className="presPanel-divider"></div>
-            <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
-            <div
-                className="presPanel-button-text"
-                onClick={() => this.gotoDocument(0, this.activeItem)}
-                style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}>
-                Slide {this.itemIndex + 1} / {this.childDocs.length}
-                {this.playButtonFrames}
-            </div>
-            <div className="presPanel-divider"></div>
-            {this.props.PanelWidth() > 250 ? <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }))}>EXIT</div>
-                : <div className="presPanel-button" onClick={undoBatch(action(() => this.layoutDoc.presStatus = "edit"))}>
-                    <FontAwesomeIcon icon={"times"} />
-                </div>}
-        </div>);
-    }
-
-    @action
-    startOrPause = () => {
-        if (this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startAutoPres(this.itemIndex);
-        else this.pauseAutoPres();
-    }
-
-    render() {
-        // calling this method for keyEvents
-        this.isPres;
-        // needed to ensure that the childDocs are loaded for looking up fields
-        this.childDocs.slice();
-        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
-        const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
-        const presEnd: boolean = !this.layoutDoc.presLoop && (this.itemIndex === this.childDocs.length - 1);
-        const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0);
-        return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ?
-            <div className="miniPres">
-                <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + PresColor.DarkBlue : undefined }}>
-                    <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? PresColor.DarkBlue : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
-                    <div className="presPanel-divider"></div>
-                    <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
-                    <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
-                    <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
-                    <div className="presPanel-divider"></div>
-                    <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
-                    <div className="presPanel-button-text">
-                        Slide {this.itemIndex + 1} / {this.childDocs.length}
-                        {this.playButtonFrames}
-                    </div>
-                    <div className="presPanel-divider"></div>
-                    <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.updateMinimize(); this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); }))}>EXIT</div>
-                </div>
-            </div>
-            :
-            <div className="presBox-cont" style={{ minWidth: CurrentUserUtils.OverlayDocs.includes(this.layoutDoc) ? 240 : undefined }} >
-                {this.topPanel}
-                {this.toolbar}
-                {this.newDocumentToolbarDropdown}
-                <div className="presBox-listCont">
-                    {mode !== CollectionViewType.Invalid ?
-                        <CollectionView {...this.props}
-                            ContainingCollectionDoc={this.props.Document}
-                            PanelWidth={this.props.PanelWidth}
-                            PanelHeight={this.panelHeight}
-                            childIgnoreNativeSize={true}
-                            moveDocument={returnFalse}
-                            childFitWidth={returnTrue}
-                            childOpacity={returnOne}
-                            childLayoutTemplate={this.childLayoutTemplate}
-                            filterAddDocument={this.addDocumentFilter}
-                            removeDocument={returnFalse}
-                            dontRegisterView={true}
-                            focus={this.selectElement}
-                            ScreenToLocalTransform={this.getTransform}
-                        />
-                        : (null)
-                    }
-                </div>
-            </div>;
-    }
-}
-Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, data: Doc) {
-    if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
-    if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 35 : 31;
-    if (field === 'presStatus') return container.presStatus;
-    if (field === '_itemIndex') return container._itemIndex;
-    if (field === 'presBox') return container;
-    return undefined;
-});
\ No newline at end of file
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 59b2d3753..d1c91cbb9 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -963,7 +963,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
             this.createHighlighterButton(),
             this.createLinkButton(),
             this.createBrushButton(),
-            <div className="richTextMenu-divider" key="divider 2" />,
+            <div className="collectionMenu-divider" key="divider 2" />,
             this.createButton("align-left", "Align Left", this.activeAlignment === "left", this.alignLeft),
             this.createButton("align-center", "Align Center", this.activeAlignment === "center", this.alignCenter),
             this.createButton("align-right", "Align Right", this.activeAlignment === "right", this.alignRight),
@@ -976,7 +976,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
         const row2 = <div className="antimodeMenu-row row-2" key="row2">
             {this.collapsed ? this.getDragger() : (null)}
             <div key="row 2" style={{ display: this.collapsed ? "none" : undefined }}>
-                <div className="richTextMenu-divider" key="divider 3" />
+                <div className="collectionMenu-divider" key="divider 3" />
                 {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => {
                     this.activeFontSize = val;
                     SelectionManager.Views().map(dv => dv.props.Document._fontSize = val);
@@ -985,12 +985,12 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
                     this.activeFontFamily = val;
                     SelectionManager.Views().map(dv => dv.props.Document._fontFamily = val);
                 })),
-                <div className="richTextMenu-divider" key="divider 4" />,
+                <div className="collectionMenu-divider" key="divider 4" />,
                 this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})),
                 this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
                 this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
-                this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
-                <div className="richTextMenu-divider" key="divider 5" />,]}
+                this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule)
+                ]}
             </div>
             {/* <div key="collapser">
                 {<div key="collapser">
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
new file mode 100644
index 000000000..06932d145
--- /dev/null
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -0,0 +1,1243 @@
+@import "../../global/globalCssVariables";
+
+.presBox-cont {
+    cursor: auto;
+    position: absolute;
+    display: block;
+    pointer-events: inherit;
+    z-index: 2;
+    font-family: Roboto;
+    width: 100%;
+    min-width: 20px;
+    height: 100%;
+    min-height: 35px;
+    letter-spacing: 2px;
+    overflow: hidden;
+    transition: 0.7s opacity ease;
+
+    .presBox-listCont {
+        position: relative;
+        height: calc(100% - 67px);
+        width: 100%;
+    }
+
+    .presBox-toolbar-dropdown {
+        border-radius: 5px;
+        background-color: white;
+        transform: translate(8px, -5px);
+        box-shadow: 1px 1px 4px 4px rgba(0, 0, 0, 0.25);
+        z-index: 1000;
+        width: calc(100% - 50px);
+        height: max-content;
+        justify-self: center;
+        letter-spacing: normal;
+        height: max-content;
+        font-weight: 500;
+        position: relative;
+        font-size: 13;
+    }
+
+    .presBox-toolbar {
+        position: relative;
+        display: inline-flex;
+        align-items: center;
+        height: 30px;
+        width: 100%;
+        color: $white;
+        background-color: $dark-gray;
+
+        .toolbar-button {
+            cursor: pointer;
+            margin-left: 10px;
+            margin-right: 10px;
+            letter-spacing: 0;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            transition: 0.5s;
+        }
+
+        .toolbar-button.active {
+            color: $light-blue;
+            background-color: white;
+            border-radius: 100%;
+        }
+
+        .toolbar-transitionButtons {
+            display: block;
+
+            .toolbar-transition {
+                display: flex;
+                font-size: 10;
+                width: 100;
+                background-color: rgba(0, 0, 0, 0);
+                min-width: max-content;
+
+                .toolbar-icon {
+                    margin-right: 5px;
+                }
+            }
+        }
+    }
+
+    .toolbar-moreInfo {
+        position: absolute;
+        right: 5px;
+        display: flex;
+        width: max-content;
+        height: 25px;
+        justify-content: center;
+        transform: rotate(90deg);
+        align-items: center;
+        transition: 0.7s ease;
+
+        .toolbar-moreInfoBall {
+            width: 4px;
+            height: 4px;
+            border-radius: 100%;
+            background-color: white;
+            margin: 1px;
+            position: relative;
+        }
+    }
+
+    .toolbar-moreInfo.active {
+        transform: rotate(0deg);
+    }
+
+    .toolbar-divider {
+        border-left: solid $medium-gray 0.5px;
+        height: 20px;
+    }
+}
+
+.dropdown {
+    font-size: 10;
+    margin-left: 5px;
+    color: $medium-gray;
+    transition: 0.5s ease;
+}
+
+.dropdown.active {
+    transform: rotate(180deg);
+    color: $light-blue;
+    opacity: 0.8;
+}
+
+.presBox-radioButtons {
+    font-size: 10px;
+    font-weight: 200;
+    // background-color: rgba(0, 0, 0, 0.1);
+
+    .checkbox-container {
+        margin-left: 10px;
+        display: inline-flex;
+        width: 100%;
+        height: 20px;
+        align-items: center;
+    }
+
+    .checkbox-dropdown {
+        display: flex;
+        width: 100%;
+        align-items: flex-end;
+        gap: 5px;
+
+        .presBox-viewPicker {
+            width: calc(100% - 120px);
+            min-width: 30px;
+        }
+    }
+}
+
+.presBox-ribbon {
+    position: relative;
+    display: inline;
+    font-family: Roboto;
+    z-index: 100;
+    transition: 0.7s;
+
+    .ribbon-doubleButton {
+        display: inline-flex;
+    }
+
+    .presBox-reactiveGrid {
+        display: grid;
+        justify-content: flex-start;
+        align-items: center;
+        grid-template-columns: repeat(auto-fit, 70px);
+    }
+
+    .ribbon-colorBox {
+        cursor: pointer;
+        border: solid 1px $black;
+        display: flex;
+        margin-left: 5px;
+        margin-top: 5px;
+        margin-bottom: 5px;
+        justify-content: center;
+        align-items: center;
+        height: 15px;
+        width: 15px;
+        padding: 0px;
+        transform: translate(2px, 3px);
+    }
+
+    .ribbon-property {
+        font-size: 11;
+        font-weight: 200;
+        height: 20;
+        background-color: $white;
+        color: $black;
+        border: solid 1px $black;
+        display: flex;
+        margin-left: 5px;
+        margin-top: 5px;
+        margin-bottom: 5px;
+        width: max-content;
+        justify-content: center;
+        align-items: center;
+        padding-right: 10px;
+        padding-left: 10px;
+    }
+
+    .ribbon-propertyUpDown {
+        height: 20;
+        width: 20;
+        margin-top: 5px;
+        display: grid;
+        grid-template-rows: 10px 10px;
+
+        .ribbon-propertyUpDownItem {
+            cursor: pointer;
+            color: white;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            height: 100%;
+            width: 100%;
+            background: $black;
+        }
+
+        .ribbon-propertyUpDownItem:hover {
+            background: $medium-gray;
+            transform: scale(1.05);
+        }
+    }
+
+    .presBox-subheading {
+        font-size: 11;
+        font-weight: 400;
+        margin-top: 10px;
+    }
+
+    @media screen and (-webkit-min-device-pixel-ratio:0) {
+
+        .multiThumb-slider {
+            display: grid;
+            background-color: $white;
+            height: 10px;
+            border-radius: 10px;
+            overflow: hidden;
+
+            .toolbar-slider {
+                margin-top: 0px;
+                background: none;
+                -webkit-appearance: none;
+                pointer-events: none;
+            }
+
+            .toolbar-slider.start::-webkit-slider-thumb {
+                width: 10px;
+                pointer-events: auto;
+                -webkit-appearance: none;
+                height: 10px;
+                cursor: ew-resize;
+                background: $medium-blue;
+                box-shadow: -100vw 0 0 100vw $white;
+            }
+
+            .toolbar-slider.end::-webkit-slider-thumb {
+                width: 10px;
+                pointer-events: auto;
+                -webkit-appearance: none;
+                height: 10px;
+                cursor: ew-resize;
+                background: $medium-blue;
+                box-shadow: -100vw 0 0 100vw $light-blue;
+            }
+        }
+
+        .toolbar-slider {
+            margin-top: 5px;
+            position: relative;
+            align-self: center;
+            justify-self: left;
+            overflow: hidden;
+            width: 100%;
+            height: 10px;
+            border-radius: 10px;
+            -webkit-appearance: none;
+            background-color: $white;
+        }
+
+        .toolbar-slider:focus {
+            outline: none;
+        }
+
+        .toolbar-slider::-webkit-slider-runnable-track {
+            height: 10px;
+            -webkit-appearance: none;
+            margin-top: -1px;
+        }
+
+        .toolbar-slider::-webkit-slider-thumb {
+            width: 10px;
+            pointer-events: auto;
+            -webkit-appearance: none;
+            height: 10px;
+            cursor: ew-resize;
+            background: $medium-blue;
+            box-shadow: -100vw 0 0 100vw $light-blue;
+        }
+
+        .presBox-checkbox {
+            -webkit-appearance: none;
+            -webkit-user-select: none;
+            -moz-user-select: none;
+            -ms-user-select: none;
+            user-select: none;
+            margin: 0;
+            margin-right: 3px;
+            border-radius: 100%;
+            height: 15px;
+            width: 15px;
+            min-width: 15px;
+            cursor: pointer;
+            background: $white;
+        }
+
+        .presBox-checkbox:focus {
+            outline: none;
+        }
+
+        .presBox-checkbox:hover {
+            background: $light-gray;
+        }
+
+        .presBox-checkbox:checked {
+            background: $light-blue;
+        }
+    }
+
+
+
+    .slider-headers {
+        position: relative;
+        display: grid;
+        justify-content: space-between;
+        width: 100%;
+        height: max-content;
+        grid-template-columns: auto auto auto;
+        grid-template-rows: max-content;
+        font-weight: 100;
+        margin-top: 3px;
+        font-size: 10px;
+
+        .slider-block {
+            width: 63px;
+            border-radius: 5px;
+            text-align: center;
+            margin-bottom: 8px;
+            margin-top: 8px;
+        }
+
+        .slider-number {
+            border-radius: 3px;
+            width: 30px;
+            margin: auto;
+        }
+    }
+
+    .slider-value {
+        top: -20;
+        color: #2f86a2;
+        position: absolute;
+    }
+
+    .slider-value.none,
+    .slider-headers.none,
+    .toolbar-slider.none {
+        display: none;
+    }
+
+    .dropdown-header {
+        padding-bottom: 10px;
+        font-weight: 800;
+        text-align: center;
+        font-size: 16;
+        width: 90%;
+        color: $black;
+        transform: translate(5%, 0px);
+        border-bottom: solid 2px $medium-gray;
+    }
+
+
+    .ribbon-textInput {
+        border-radius: 2px;
+        height: 20px;
+        font-size: 11.5;
+        font-weight: 100;
+        align-self: center;
+        justify-self: left;
+        margin-top: 5px;
+        padding-left: 10px;
+        background-color: $white;
+        border: solid 1px $black;
+        min-width: 80px;
+        max-width: 200px;
+        width: 100%;
+    }
+
+    .presBox-input {
+        width: 30;
+        height: 100%;
+        background: none;
+        border: none;
+        text-align: right;
+    }
+
+    .presBox-input:focus {
+        outline: none;
+    }
+
+    .ribbon-frameSelector {
+        border: $black solid 1px;
+        width: 60px;
+        height: 20px;
+        margin-top: 5px;
+        display: grid;
+        grid-template-columns: auto 27px auto;
+        position: relative;
+        border-radius: 5px;
+        overflow: hidden;
+        align-items: center;
+        justify-self: left;
+
+        .fwdKeyframe,
+        .backKeyframe {
+            cursor: pointer;
+            position: relative;
+            height: 100%;
+            background: $white;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            text-align: center;
+            color: $black;
+        }
+
+        .numKeyframe {
+            cursor: pointer;
+            font-size: 10;
+            font-weight: 600;
+            position: relative;
+            color: $black;
+            display: flex;
+            width: 100%;
+            height: 100%;
+            text-align: center;
+            align-items: center;
+            justify-content: center;
+        }
+    }
+
+    .ribbon-final-box {
+        align-self: flex-start;
+        justify-self: center;
+        display: grid;
+        margin-top: 10px;
+        grid-template-rows: auto auto;
+        /* padding-left: 10px; */
+        /* padding-right: 10px; */
+        letter-spacing: normal;
+        min-width: max-content;
+        width: 100%;
+        font-size: 13;
+        font-weight: 500;
+        position: relative;
+
+
+        .ribbon-final-button {
+            cursor: pointer;
+            position: relative;
+            font-size: 11;
+            font-weight: normal;
+            letter-spacing: normal;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-bottom: 5px;
+            height: 25px;
+            color: white;
+            width: 100%;
+            max-width: 120;
+            padding-left: 10;
+            padding-right: 10;
+            border-radius: 10px;
+            background-color: $medium-gray;
+        }
+
+        .ribbon-final-button:hover {
+            transform: scale(1.05);
+            transition: all 0.4s;
+        }
+
+        .ribbon-final-button-hidden {
+            cursor: pointer;
+            position: relative;
+            font-size: 11;
+            font-weight: normal;
+            letter-spacing: normal;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin-bottom: 5px;
+            height: 25px;
+            color: $light-gray;
+            width: 100%;
+            max-width: 120;
+            padding-left: 10;
+            padding-right: 10;
+            border-radius: 10px;
+            background-color: $black;
+        }
+
+        .ribbon-final-button-hidden:hover {
+            transform: scale(1.05);
+            transition: all 0.4s;
+        }
+
+        .ribbon-frameList {
+            width: calc(100% - 5px);
+            height: 50px;
+            background-color: $white;
+            border: 1px solid $medium-gray;
+            grid-template-rows: max-content;
+
+            .frameList-header {
+                display: grid;
+                width: 100%;
+                height: 20px;
+                background-color: $medium-gray;
+
+                .frameList-headerButtons {
+                    display: flex;
+                    grid-column: 7;
+                    width: 60px;
+                    justify-self: right;
+                    justify-content: flex-end;
+
+                    .headerButton {
+                        cursor: pointer;
+                        position: relative;
+                        border-radius: 100%;
+                        z-index: 300;
+                        width: 15px;
+                        height: 15px;
+                        display: flex;
+                        font-size: 10px;
+                        justify-self: center;
+                        align-self: center;
+                        background-color: rgba(0, 0, 0, 0.5);
+                        color: white;
+                        justify-content: center;
+                        align-items: center;
+                        transition: 0.2s;
+                        margin-right: 3px;
+                    }
+
+                    .headerButton:hover {
+                        background-color: rgba(0, 0, 0, 1);
+                        transform: scale(1.15);
+                    }
+                }
+            }
+        }
+    }
+
+    .selectedList {
+        display: block;
+        min-width: 50;
+        max-width: 120;
+        height: 70;
+        overflow-y: scroll;
+
+        .selectedList-items {
+            font-size: 7;
+            font-weight: normal;
+        }
+    }
+
+    .ribbon-button {
+        cursor: pointer;
+        font-size: 10.5;
+        font-weight: 300;
+        height: 20;
+        background-color: $medium-gray;
+        color: white;
+        display: flex;
+        margin-top: 5px;
+        margin-bottom: 5px;
+        border-radius: 5px;
+        margin-right: 5px;
+        width: max-content;
+        justify-content: center;
+        align-items: center;
+        padding-right: 10px;
+        padding-left: 10px;
+    }
+
+    .ribbon-button:hover {
+        transform: scale(1.03);
+        transition: all 0.4s;
+        font-weight: 400;
+        opacity: 1;
+        color: $white;
+        background-color: $black;
+    }
+
+    .ribbon-toggle {
+        cursor: pointer;
+        font-size: 10.5;
+        font-weight: 200;
+        height: 20;
+        background-color: $white;
+        border: solid 1px rgba(0, 0, 0, 0.5);
+        display: flex;
+        color: $black;
+        margin-top: 5px;
+        margin-bottom: 5px;
+        border-radius: 5px;
+        margin-right: 5px;
+        width: max-content;
+        justify-content: center;
+        align-items: center;
+        padding-right: 10px;
+        padding-left: 10px;
+    }
+
+    .ribbon-toggle.active {
+        background-color: #aedef8;
+    }
+
+    .ribbon-toggle:hover {
+        transform: scale(1.03);
+        transition: all 0.4s;
+        border: solid 1px rgba(0, 0, 0, 0.75);
+    }
+
+    svg.svg-inline--fa.fa-thumbtack.fa-w-12.toolbar-thumbtack {
+        right: 40;
+        position: absolute;
+        transform: rotate(45deg);
+    }
+
+    .ribbon-box {
+        display: grid;
+        grid-template-rows: max-content auto;
+        justify-self: center;
+        margin-top: 10px;
+        padding-right: 10px;
+        letter-spacing: normal;
+        width: 100%;
+        height: max-content;
+        font-weight: 500;
+        position: relative;
+        font-size: 13;
+        padding-bottom: 10px;
+        border-bottom: solid 1px $dark-gray;
+
+        .presBox-dropdown:hover {
+            border: solid 1px $medium-blue;
+
+            .presBox-dropdownIcon {
+                color: $medium-blue;
+            }
+        }
+
+        .presBox-dropdown {
+            cursor: pointer;
+            display: grid;
+            grid-template-columns: auto 20%;
+            position: relative;
+            border: solid 1px $black;
+            background-color: $light-gray;
+            border-radius: 5px;
+            font-size: 10;
+            height: 25;
+            color: $black;
+            padding-left: 5px;
+            align-items: center;
+            margin-top: 5px;
+            margin-bottom: 5px;
+            font-weight: 200;
+            width: 100%;
+            min-width: max-content;
+            max-width: 200px;
+            overflow: visible;
+
+
+            .presBox-dropdownOption {
+                cursor: pointer;
+                font-size: 11;
+                display: block;
+                padding-left: 10px;
+                padding-right: 5px;
+                padding-top: 3;
+                padding-bottom: 3;
+            }
+
+            .presBox-dropdownOption:hover {
+                position: relative;
+                background-color: lightgrey;
+            }
+
+            .presBox-dropdownOption.active {
+                position: relative;
+                background-color: $light-blue;
+            }
+
+            .presBox-dropdownOptions {
+                position: absolute;
+                top: 23px;
+                left: -2px;
+                z-index: 200;
+                width: 85%;
+                min-width: max-content;
+                display: block;
+                background: #FFFFFF;
+                border: 0.5px solid #979797;
+                box-sizing: border-box;
+                box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
+            }
+
+            .presBox-dropdownIcon {
+                position: relative;
+                color: black;
+                align-self: center;
+                justify-self: center;
+                margin-right: 2px;
+            }
+        }
+    }
+}
+
+.presBox-ribbon.active {
+    display: grid;
+    grid-template-columns: auto auto auto auto auto;
+    grid-template-rows: 100%;
+    height: 100px;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    border: solid 1px $black;
+    // overflow: auto; 
+
+    ::-webkit-scrollbar {
+        -webkit-appearance: none;
+        height: 3px;
+        width: 8px;
+    }
+
+    ::-webkit-scrollbar-thumb {
+        border-radius: 2px;
+    }
+}
+
+.dropdown-play-button {
+    cursor: pointer;
+    font-size: 12;
+    padding-left: 5px;
+    padding-right: 5px;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    text-align: left;
+    justify-content: left;
+}
+
+.dropdown-play-button:hover {
+    background-color: lightgrey;
+}
+
+.presBox-button-left {
+    cursor: pointer;
+    position: relative;
+    align-self: flex-start;
+    justify-self: flex-start;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 4px;
+    padding-left: 7px;
+    padding-right: 7px;
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+}
+
+.presBox-button-right {
+    cursor: pointer;
+    position: relative;
+    text-align: center;
+    border-left: solid 1px $medium-gray;
+    width: 20%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 4px;
+    padding-left: 7px;
+    padding-right: 7px;
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+}
+
+.presBox-button-right.active {
+    background-color: #223063;
+    border: #aedcf6 solid 1px;
+    box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
+}
+
+.dropdown-play {
+    cursor: pointer;
+    right: 0px;
+    top: calc(100% + 2px);
+    display: none;
+    border-radius: 5px;
+    width: max-content;
+    min-height: 20px;
+    height: max-content;
+    box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8);
+    z-index: 200;
+    background-color: white;
+    color: $black;
+    position: absolute;
+    overflow: hidden;
+}
+
+.dropdown-play.active {
+    display: block;
+}
+
+.open-layout {
+    cursor: pointer;
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transform: translate(0px, -1px);
+    background-color: $white;
+    width: 40px;
+    height: 15px;
+    align-self: center;
+    justify-self: center;
+    border: solid 1px $black;
+    border-top: 0px;
+    border-bottom-right-radius: 7px;
+    border-bottom-left-radius: 7px;
+}
+
+.layout-container {
+    padding: 5px;
+    display: grid;
+    background-color: $white;
+    grid-template-columns: repeat(auto-fit, minmax(90px, 100px));
+    width: 100%;
+    border: solid 1px $black;
+    min-width: 100px;
+    overflow: hidden;
+
+    .layout:hover {
+        border: solid 2px $medium-blue;
+    }
+
+    .layout {
+        cursor: pointer;
+        align-self: center;
+        justify-self: center;
+        margin-top: 5;
+        margin-bottom: 5;
+        position: relative;
+        height: 55px;
+        min-width: 90px;
+        width: 90px;
+        overflow: hidden;
+        background-color: white;
+        border: solid $medium-gray 1px;
+        display: grid;
+        grid-template-rows: auto;
+        align-items: center;
+        text-align: center;
+
+        .title {
+            position: relative;
+            align-self: end;
+            padding-left: 3px;
+            margin-left: 3px;
+            margin-right: 3px;
+            height: 13;
+            font-size: 12;
+            display: flex;
+            background-color: $white;
+        }
+
+        .subtitle {
+            align-self: flex-start;
+            position: relative;
+            padding-left: 3px;
+            margin-left: 3px;
+            margin-right: 3px;
+            font-weight: 400;
+            height: 13;
+            font-size: 9;
+            display: flex;
+            background-color: $white;
+        }
+
+        .content {
+            position: relative;
+            font-weight: 200;
+            align-self: flex-start;
+            padding-left: 3px;
+            margin-left: 3px;
+            margin-right: 3px;
+            height: 13;
+            font-size: 10;
+            display: flex;
+            background-color: $white;
+            height: 33;
+            text-align: left;
+            font-size: 8px;
+        }
+    }
+}
+
+.presBox-buttons {
+    position: relative;
+    width: 100%;
+    background: $medium-gray;
+    min-height: 35px;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    display: grid;
+    grid-template-columns: auto auto;
+
+    .presBox-viewPicker {
+        cursor: pointer;
+        height: 25;
+        position: relative;
+        display: inline-block;
+        grid-column: 1;
+        border-radius: 5px;
+        min-width: 15px;
+        max-width: 100px;
+        left: 8px;
+    }
+
+    .presBox-presentPanel {
+        display: flex;
+        justify-self: end;
+        width: 100%;
+        max-width: 300px;
+        min-width: 150px;
+    }
+
+
+
+    select {
+        background: $dark-gray;
+        color: $white;
+    }
+
+    .presBox-button {
+        cursor: pointer;
+        height: 25px;
+        border-radius: 5px;
+        display: none;
+        justify-content: center;
+        align-content: center;
+        align-items: center;
+        text-align: center;
+        letter-spacing: normal;
+        width: inherit;
+        background: $dark-gray;
+        color: $white;
+    }
+
+    .presBox-button.active {
+        display: flex;
+    }
+
+    .presBox-button.active:hover {
+        background-color: $medium-blue;
+    }
+
+    .presBox-button.edit {
+        display: flex;
+        max-width: 25px;
+    }
+
+    .presBox-button.present {
+        display: flex;
+        width: max-content;
+        position: absolute;
+        right: 10px;
+
+        .present-icon {
+            margin-right: 7px;
+        }
+    }
+
+
+
+    .collectionViewBaseChrome-viewPicker {
+        min-width: 50;
+        width: 5%;
+        height: 25;
+        position: relative;
+        display: inline-block;
+        left: 8px;
+    }
+}
+
+.presBox-backward,
+.presBox-forward {
+    width: 25px;
+    border-radius: 5px;
+    top: 50%;
+    position: absolute;
+    display: inline-block;
+}
+
+.presBox-backward {
+    left: 5;
+}
+
+.presBox-forward {
+    right: 5;
+}
+
+// CSS adjusted for mobile devices
+@media only screen and (max-device-width: 480px) {
+    .presBox-cont .presBox-buttons {
+        position: absolute;
+        top: 70%;
+        left: 50%;
+        transform: translate(-50%, 0);
+        width: max-content;
+        height: 15%;
+        z-index: 2;
+        align-items: center;
+        background: rgba(0, 0, 0, 0);
+        display: inline-flex;
+
+        .presBox-button {
+            margin-top: 5%;
+            height: 250;
+            width: 300;
+            font-size: 100;
+            display: flex;
+            align-items: center;
+            background: $dark-gray;
+            color: $white;
+        }
+
+        .presBox-viewPicker {
+            top: -70;
+            left: 2.5%;
+            height: 50;
+            width: 95%;
+            font-size: 30px;
+            position: absolute;
+            min-width: 50px;
+        }
+    }
+
+    .presBox-cont .presBox-listCont {
+        top: 50;
+        height: calc(100% - 80px);
+    }
+
+    .input,
+    .select {
+        font-size: 100%;
+    }
+}
+
+.miniPres {
+    cursor: grab;
+    position: absolute;
+    right: 10;
+    top: 10;
+    opacity: 0.1;
+    transition: all 0.4s;
+    color: $white;
+}
+
+.miniPres:hover {
+    opacity: 1;
+}
+
+.presPanelOverlay {
+    background-color: $dark-gray;
+    color: $white;
+    border-radius: 5px;
+    grid-template-rows: 100%;
+    height: 25;
+    width: max-content;
+    min-width: max-content;
+    justify-content: space-evenly;
+    align-items: center;
+    display: flex;
+    position: absolute;
+    right: 10px;
+    transition: all 0.2s;
+
+    .presPanel-button-text {
+        cursor: pointer;
+        display: flex;
+        height: 20;
+        width: max-content;
+        font-family: Roboto;
+        font-weight: 400;
+        margin-left: 3px;
+        margin-right: 3px;
+        padding-right: 3px;
+        padding-left: 3px;
+        letter-spacing: normal;
+        border-radius: 5px;
+        align-items: center;
+        justify-content: center;
+        transition: all 0.3s;
+    }
+
+    .presPanel-divider {
+        width: 0.5px;
+        height: 80%;
+        border-right: solid 1px $medium-gray;
+    }
+
+    .presPanel-button-frame {
+        justify-self: center;
+        align-self: center;
+        align-items: center;
+        display: grid;
+        grid-template-columns: auto auto auto;
+        justify-content: space-around;
+        font-size: 11;
+        margin-left: 7;
+        width: 30;
+        height: 85%;
+        background-color: rgba(91, 157, 221, 0.4);
+        border-radius: 5px;
+    }
+
+    .presPanel-button {
+        cursor: pointer;
+        display: flex;
+        height: 20;
+        min-width: 20;
+        margin-left: 3px;
+        margin-right: 3px;
+        border-radius: 100%;
+        align-items: center;
+        justify-content: center;
+        transition: all 0.3s;
+    }
+
+    .presPanel-button:hover {
+        background-color: $medium-gray;
+        transform: scale(1.2);
+    }
+
+    .presPanel-button-text:hover {
+        background-color: $medium-gray;
+    }
+
+
+}
+
+// .miniPres {
+//     cursor: grab;
+//     position: absolute;
+//     overflow: hidden;
+//     right: 10;
+//     top: 10;
+//     opacity: 0.1;
+//     transition: all 0.4s;
+//     /* border: solid 1px; */
+//     color: white;
+//     /* box-shadow: black 0.4vw 0.4vw 0.8vw; */
+
+//     .miniPresOverlay {
+//         display: grid;
+//         grid-template-columns: auto auto auto auto auto auto auto auto auto auto;
+//         grid-template-rows: 100%;
+//         height: 100%;
+//         justify-items: center;
+//         align-items: center;
+
+//         .miniPres-button-text {
+//             cursor: pointer;
+//             display: flex;
+//             height: 20;
+//             font-weight: 400;
+//             min-width: 100%;
+//             border-radius: 5px;
+//             align-items: center;
+//             justify-content: center;
+//             transition: all 0.3s;
+//         }
+
+//         .miniPres-button-frame {
+//             justify-self: center;
+//             align-self: center;
+//             align-items: center;
+//             display: grid;
+//             grid-template-columns: auto auto auto;
+//             justify-content: space-around;
+//             font-size: 11;
+//             margin-left: 7;
+//             width: 30;
+//             height: 85%;
+//             background-color: rgba(91, 157, 221, 0.4);
+//             border-radius: 5px;
+//         }
+
+//         .miniPres-divider {
+//             width: 0.5px;
+//             height: 80%;
+//             border-right: solid 2px #5a5a5a;
+//         }
+
+//         .miniPres-button {
+//             cursor: pointer;
+//             display: flex;
+//             height: 20;
+//             min-width: 20;
+//             border-radius: 100%;
+//             align-items: center;
+//             justify-content: center;
+//             transition: all 0.3s;
+//         }
+
+//         .miniPres-button:hover {
+//             background-color: #5a5a5a;
+//         }
+
+//         .miniPres-button-text:hover {
+//             background-color: #5a5a5a;
+//         }
+//     }
+// }
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
new file mode 100644
index 000000000..5cb9866f8
--- /dev/null
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -0,0 +1,2440 @@
+import React = require("react");
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { ColorState, SketchPicker } from "react-color";
+import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal';
+import { Doc, DocListCast, DocListCastAsync, FieldResult } from "../../../../fields/Doc";
+import { documentSchema } from "../../../../fields/documentSchemas";
+import { InkTool } from "../../../../fields/InkField";
+import { List } from "../../../../fields/List";
+import { PrefetchProxy } from "../../../../fields/Proxy";
+import { listSpec, makeInterface } from "../../../../fields/Schema";
+import { ScriptField } from "../../../../fields/ScriptField";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types";
+import { emptyFunction, returnFalse, returnOne, returnTrue } from '../../../../Utils';
+import { Docs } from "../../../documents/Documents";
+import { DocumentType } from "../../../documents/DocumentTypes";
+import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
+import { DocumentManager } from "../../../util/DocumentManager";
+import { Scripting } from "../../../util/Scripting";
+import { SelectionManager } from "../../../util/SelectionManager";
+import { undoBatch, UndoManager } from "../../../util/UndoManager";
+import { CollectionDockingView } from "../../collections/CollectionDockingView";
+import { CollectionView, CollectionViewType } from "../../collections/CollectionView";
+import { TabDocView } from "../../collections/TabDocView";
+import { ViewBoxBaseComponent } from "../../DocComponent";
+import { Colors } from "../../global/globalEnums";
+import { LightboxView } from "../../LightboxView";
+import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentView";
+import { FieldView, FieldViewProps } from '../FieldView';
+import "./PresBox.scss";
+import Color = require("color");
+import { PresEffect, PresStatus, PresMovement } from "./PresEnums";
+
+export class PinProps {
+    audioRange?: boolean;
+    unpin?: boolean;
+    setPosition?: boolean;
+    hidePresBox?: boolean;
+}
+
+type PresBoxSchema = makeInterface<[typeof documentSchema]>;
+const PresBoxDocument = makeInterface(documentSchema);
+
+@observer
+export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
+
+    static renderEffectsDoc(renderDoc: any, layoutDoc: Doc) {
+        const effectProps = {
+            left: layoutDoc.presEffectDirection === PresEffect.Left,
+            right: layoutDoc.presEffectDirection === PresEffect.Right,
+            top: layoutDoc.presEffectDirection === PresEffect.Top,
+            bottom: layoutDoc.presEffectDirection === PresEffect.Bottom,
+            opposite: true,
+            delay: layoutDoc.presTransition,
+            // when: this.layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc,
+        };
+        switch (layoutDoc.presEffect) {
+            case PresEffect.Zoom: return (<Zoom {...effectProps}>{renderDoc}</Zoom>);
+            case PresEffect.Fade: return (<Fade {...effectProps}>{renderDoc}</Fade>);
+            case PresEffect.Flip: return (<Flip {...effectProps}>{renderDoc}</Flip>);
+            case PresEffect.Rotate: return (<Rotate {...effectProps}>{renderDoc}</Rotate>);
+            case PresEffect.Bounce: return (<Bounce {...effectProps}>{renderDoc}</Bounce>);
+            case PresEffect.Roll: return (<Roll {...effectProps}>{renderDoc}</Roll>);
+            case PresEffect.Lightspeed: return (<LightSpeed {...effectProps}>{renderDoc}</LightSpeed>);
+            case PresEffect.None:
+            default: return renderDoc;
+        }
+    }
+    public static EffectsProvider(layoutDoc: Doc, renderDoc: any) {
+        return PresBox.Instance && layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc ?
+            PresBox.renderEffectsDoc(renderDoc, layoutDoc)
+            :
+            renderDoc;
+    }
+
+    @observable public static Instance: PresBox;
+
+    @observable _isChildActive = false;
+    @observable _moveOnFromAudio: boolean = true;
+    @observable _presTimer!: NodeJS.Timeout;
+    @observable _presKeyEventsActive: boolean = false;
+
+    @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
+    @observable _eleArray: HTMLElement[] = [];
+    @observable _dragArray: HTMLElement[] = [];
+    @observable _pathBoolean: boolean = false;
+    @observable _expandBoolean: boolean = false;
+
+    private _disposers: { [name: string]: IReactionDisposer } = {};
+    @observable private transitionTools: boolean = false;
+    @observable private newDocumentTools: boolean = false;
+    @observable private progressivizeTools: boolean = false;
+    @observable private openMovementDropdown: boolean = false;
+    @observable private openEffectDropdown: boolean = false;
+    @observable private presentTools: boolean = false;
+    @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
+    @computed get tagDocs() {
+        const tagDocs: Doc[] = [];
+        for (const doc of this.childDocs) {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            tagDocs.push(tagDoc);
+        }
+        return tagDocs;
+    }
+    @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); }
+    @computed get activeItem() { return Cast(this.childDocs[NumCast(this.rootDoc._itemIndex)], Doc, null); }
+    @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); }
+    @computed get scrollable(): boolean {
+        if (this.targetDoc.type === DocumentType.PDF || this.targetDoc.type === DocumentType.WEB || this.targetDoc.type === DocumentType.RTF || this.targetDoc._viewType === CollectionViewType.Stacking) return true;
+        else return false;
+    }
+    @computed get panable(): boolean {
+        if ((this.targetDoc.type === DocumentType.COL && this.targetDoc._viewType === CollectionViewType.Freeform) || this.targetDoc.type === DocumentType.IMG) return true;
+        else return false;
+    }
+    @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); }
+    constructor(props: any) {
+        super(props);
+        if (Doc.UserDoc().activePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this);
+        if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations.
+            Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
+                title: "pres element template", type: DocumentType.PRESELEMENT, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"
+            }));
+            // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement
+            // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent
+            // the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data
+            // stored on each pres element.
+            (this.presElement as Doc).lookupField = ScriptField.MakeFunction("lookupPresBoxField(container, field, data)",
+                { field: "string", data: Doc.name, container: Doc.name });
+        }
+        this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox
+    }
+    @computed get selectedDocumentView() {
+        if (SelectionManager.Views().length) return SelectionManager.Views()[0];
+        if (this._selectedArray.size) return DocumentManager.Instance.getDocumentView(this.rootDoc);
+    }
+    @computed get isPres(): boolean {
+        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+        if (this.selectedDoc?.type === DocumentType.PRES) {
+            document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+            document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
+            return true;
+        }
+        return false;
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+
+    @action
+    componentWillUnmount() {
+        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+        this._presKeyEventsActive = false;
+        this.resetPresentation();
+        // Turn of progressivize editors
+        this.turnOffEdit(true);
+        Object.values(this._disposers).forEach(disposer => disposer?.());
+    }
+
+    @action
+    componentDidMount() {
+        this.rootDoc.presBox = this.rootDoc;
+        this.rootDoc._forceRenderEngine = "timeline";
+        this.layoutDoc.presStatus = PresStatus.Edit;
+        this.layoutDoc._gridGap = 0;
+        this.layoutDoc._yMargin = 0;
+        this.turnOffEdit(true);
+        DocListCastAsync((Doc.UserDoc().myPresentations as Doc).data).then(pres =>
+            !pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc));
+        this._disposers.selection = reaction(() => SelectionManager.Views(),
+            views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation());
+    }
+
+    @action
+    updateCurrentPresentation = (pres?: Doc) => {
+        if (pres) Doc.UserDoc().activePresentation = pres;
+        else Doc.UserDoc().activePresentation = this.rootDoc;
+        document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+        document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
+        this._presKeyEventsActive = true;
+        PresBox.Instance = this;
+    }
+
+    // There are still other internal frames and should go through all frames before going to next slide
+    nextInternalFrame = (targetDoc: Doc, activeItem: Doc) => {
+        const currentFrame = Cast(targetDoc?._currentFrame, "number", null);
+        const childDocs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+        targetDoc._viewTransition = "all 1s";
+        setTimeout(() => targetDoc._viewTransition = undefined, 1010);
+        this.nextKeyframe(targetDoc, activeItem);
+        if (activeItem.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, targetDoc);
+        else targetDoc.keyFrameEditing = true;
+    }
+
+    _mediaTimer!: [NodeJS.Timeout, Doc];
+    // 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played
+    startTempMedia = (targetDoc: Doc, activeItem: Doc) => {
+        const duration: number = NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime);
+        if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
+            const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
+            targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.presStartTime), NumCast(activeItem.presStartTime) + duration);
+        }
+        // if (targetDoc.type === DocumentType.AUDIO) {
+        //     if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
+        //     targetDoc._triggerAudio = NumCast(activeItem.presStartTime);
+        //     this._mediaTimer = [setTimeout(() => targetDoc._audioStop = true, duration * 1000), targetDoc];
+        // } else if (targetDoc.type === DocumentType.VID) {
+        //     targetDoc._triggerVideoStop = true;
+        //     setTimeout(() => targetDoc._currentTimecode = NumCast(activeItem.presStartTime), 10);
+        //     setTimeout(() => targetDoc._triggerVideo = true, 20);
+        //     this._mediaTimer = [setTimeout(() => targetDoc._triggerVideoStop = true, (duration * 1000) + 20), targetDoc];
+        // }
+    }
+
+    stopTempMedia = (targetDocField: FieldResult) => {
+        const targetDoc = Cast(targetDocField, Doc, null);
+        if (targetDoc?.type === DocumentType.AUDIO) {
+            if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
+            targetDoc._audioStop = true;
+        } else if (targetDoc?.type === DocumentType.VID) {
+            if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
+            targetDoc._triggerVideoStop = true;
+        }
+    }
+
+    // No more frames in current doc and next slide is defined, therefore move to next slide 
+    nextSlide = (activeNext: Doc) => {
+        const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
+        let nextSelected = this.itemIndex + 1;
+        this.gotoDocument(nextSelected, this.activeItem);
+        for (nextSelected = nextSelected + 1; nextSelected < this.childDocs.length; nextSelected++) {
+            if (!this.childDocs[nextSelected].groupWithUp) {
+                break;
+            } else {
+                console.log("Title: " + this.childDocs[nextSelected].title);
+                this.gotoDocument(nextSelected, this.activeItem, true);
+            }
+        }
+    }
+
+    // Called when the user activates 'next' - to move to the next part of the pres. trail
+    @action
+    next = () => {
+        const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null);
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const lastFrame = Cast(targetDoc?.lastFrame, "number", null);
+        const curFrame = NumCast(targetDoc?._currentFrame);
+        let internalFrames: boolean = false;
+        if (activeItem.presProgressivize || activeItem.zoomProgressivize || targetDoc.scrollProgressivize) internalFrames = true;
+        if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) {
+            // Case 1: There are still other frames and should go through all frames before going to next slide
+            this.nextInternalFrame(targetDoc, activeItem);
+        } else if (this.childDocs[this.itemIndex + 1] !== undefined) {
+            // Case 2: No more frames in current doc and next slide is defined, therefore move to next slide 
+            this.nextSlide(activeNext);
+        } else if (this.childDocs[this.itemIndex + 1] === undefined && (this.layoutDoc.presLoop || this.layoutDoc.presStatus === PresStatus.Edit)) {
+            // Case 3: Last slide and presLoop is toggled ON or it is in Edit mode
+            this.gotoDocument(0, this.activeItem);
+        }
+    }
+
+    // Called when the user activates 'back' - to move to the previous part of the pres. trail
+    @action
+    back = () => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const prevItem = Cast(this.childDocs[Math.max(0, this.itemIndex - 1)], Doc, null);
+        const prevTargetDoc = Cast(prevItem.presentationTargetDoc, Doc, null);
+        const lastFrame = Cast(targetDoc.lastFrame, "number", null);
+        const curFrame = NumCast(targetDoc._currentFrame);
+        let prevSelected = this.itemIndex;
+        // Functionality for group with up
+        let didZoom = activeItem.presMovement;
+        for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) {
+            didZoom = this.childDocs[prevSelected].presMovement;
+        }
+        if (lastFrame !== undefined && curFrame >= 1) {
+            // Case 1: There are still other frames and should go through all frames before going to previous slide
+            this.prevKeyframe(targetDoc, activeItem);
+        } else if (activeItem && this.childDocs[this.itemIndex - 1] !== undefined) {
+            // Case 2: There are no other frames so it should go to the previous slide
+            prevSelected = Math.max(0, prevSelected - 1);
+            this.gotoDocument(prevSelected, activeItem);
+            if (NumCast(prevTargetDoc.lastFrame) > 0) prevTargetDoc._currentFrame = NumCast(prevTargetDoc.lastFrame);
+        } else if (this.childDocs[this.itemIndex - 1] === undefined && this.layoutDoc.presLoop) {
+            // Case 3: Pres loop is on so it should go to the last slide
+            this.gotoDocument(this.childDocs.length - 1, activeItem);
+        }
+    }
+
+    //The function that is called when a document is clicked or reached through next or back.
+    //it'll also execute the necessary actions if presentation is playing.
+    public gotoDocument = action((index: number, from?: Doc, group?: boolean) => {
+        Doc.UnBrushAllDocs();
+        if (index >= 0 && index < this.childDocs.length) {
+            this.rootDoc._itemIndex = index;
+            const activeItem: Doc = this.activeItem;
+            const targetDoc: Doc = this.targetDoc;
+            if (from?.mediaStopTriggerList && this.layoutDoc.presStatus !== PresStatus.Edit) {
+                DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
+            }
+            if (from?.mediaStop === "auto" && this.layoutDoc.presStatus !== PresStatus.Edit) {
+                this.stopTempMedia(from.presentationTargetDoc);
+            }
+            // If next slide is audio / video 'Play automatically' then the next slide should be played
+            if (this.layoutDoc.presStatus !== PresStatus.Edit && (targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && (activeItem.mediaStart === "auto")) {
+                this.startTempMedia(targetDoc, activeItem);
+            }
+            if (targetDoc) {
+                targetDoc && runInAction(() => {
+                    if (activeItem.presMovement === PresMovement.Jump) targetDoc.focusSpeed = 0;
+                    else targetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
+                });
+                setTimeout(() => targetDoc.focusSpeed = 500, this.activeItem.presTransition ? NumCast(this.activeItem.presTransition) + 10 : 510);
+            }
+            if (targetDoc?.lastFrame !== undefined) {
+                targetDoc._currentFrame = 0;
+            }
+            if (!group) this._selectedArray.clear();
+            this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
+            if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
+            this.onHideDocument(); //Handles hide after/before
+        }
+    });
+
+    _navTimer!: NodeJS.Timeout;
+    navigateToView = (targetDoc: Doc, activeItem: Doc) => {
+        clearTimeout(this._navTimer);
+        const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
+        bestTarget && runInAction(() => {
+            if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) {
+                bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
+                bestTarget._scrollTop = activeItem.presPinViewScroll;
+            } else if (bestTarget.type === DocumentType.COMPARISON) {
+                bestTarget._clipWidth = activeItem.presPinClipWidth;
+            } else if (bestTarget.type === DocumentType.VID) {
+                bestTarget._currentTimecode = activeItem.presPinTimecode;
+            } else {
+                bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
+                bestTarget._panX = activeItem.presPinViewX;
+                bestTarget._panY = activeItem.presPinViewY;
+                bestTarget._viewScale = activeItem.presPinViewScale;
+            }
+            this._navTimer = setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510);
+        });
+    }
+
+    /**
+     * This method makes sure that cursor navigates to the element that
+     * has the option open and last in the group. 
+     * Design choice: If the next document is not in presCollection or 
+     * presCollection itself then if there is a presCollection it will add
+     * a new tab. If presCollection is undefined it will open the document
+     * on the right. 
+     */
+    navigateToElement = async (curDoc: Doc) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const srcContext = Cast(targetDoc.context, Doc, null);
+        const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
+        const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
+        const includesDoc: boolean = DocListCast(presCollection?.data).includes(targetDoc);
+        const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === srcContext);
+        this.turnOffEdit();
+        // Handles the setting of presCollection
+        if (includesDoc) {
+            //Case 1: Pres collection should not change as it is already the same
+        } else if (tab !== undefined) {
+            // Case 2: Pres collection should update
+            this.layoutDoc.presCollection = srcContext;
+        }
+        const presStatus = this.rootDoc.presStatus;
+        const selViewCache = Array.from(this._selectedArray.keys());
+        const dragViewCache = Array.from(this._dragArray);
+        const eleViewCache = Array.from(this._eleArray);
+        const self = this;
+        const resetSelection = action(() => {
+            const presDocView = DocumentManager.Instance.getDocumentView(self.rootDoc);
+            if (presDocView) SelectionManager.SelectView(presDocView, false);
+            self.rootDoc.presStatus = presStatus;
+            self._selectedArray.clear();
+            selViewCache.forEach(doc => self._selectedArray.set(doc, undefined));
+            self._dragArray.splice(0, self._dragArray.length, ...dragViewCache);
+            self._eleArray.splice(0, self._eleArray.length, ...eleViewCache);
+        });
+        const openInTab = (doc: Doc, finished?: () => void) => {
+            collectionDocView ? collectionDocView.props.addDocTab(doc, "") : this.props.addDocTab(doc, ":left");
+            this.layoutDoc.presCollection = targetDoc;
+            // this still needs some fixing
+            setTimeout(resetSelection, 500);
+            if (doc !== targetDoc) {
+                setTimeout(finished ?? emptyFunction, 100); /// give it some time to create the targetDoc if we're opening up its context
+            } else {
+                finished?.();
+            }
+        };
+        // If openDocument is selected then it should open the document for the user
+        if (activeItem.openDocument) {
+            LightboxView.SetLightboxDoc(targetDoc);
+        } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
+            LightboxView.SetLightboxDoc(undefined);
+            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right
+        } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
+            LightboxView.SetLightboxDoc(undefined);
+            //awaiting jump so that new scale can be found, since jumping is async     
+            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right    
+        }
+        // After navigating to the document, if it is added as a presPinView then it will
+        // adjust the pan and scale to that of the pinView when it was added.
+        if (activeItem.presPinView) {
+            // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target
+            this.navigateToView(targetDoc, activeItem);
+        }
+        // TODO: Add progressivize for navigating web (storing websites for given frames)
+
+    }
+
+    /**
+     * Uses the viewfinder to progressivize through the different views of a single collection.
+     * @param presTargetDoc: document for which internal zoom is used
+     */
+    zoomProgressivizeNext = (activeItem: Doc) => {
+        const targetDoc: Doc = this.targetDoc;
+        const srcContext = Cast(targetDoc?.context, Doc, null);
+        const docView = DocumentManager.Instance.getDocumentView(targetDoc);
+        const vfLeft = this.checkList(targetDoc, activeItem["viewfinder-left-indexed"]);
+        const vfWidth = this.checkList(targetDoc, activeItem["viewfinder-width-indexed"]);
+        const vfTop = this.checkList(targetDoc, activeItem["viewfinder-top-indexed"]);
+        const vfHeight = this.checkList(targetDoc, activeItem["viewfinder-height-indexed"]);
+        // Case 1: document that is not a Golden Layout tab
+        if (srcContext) {
+            const srcDocView = DocumentManager.Instance.getDocumentView(srcContext);
+            if (srcDocView) {
+                const layoutdoc = Doc.Layout(targetDoc);
+                const panelWidth: number = srcDocView.props.PanelWidth();
+                const panelHeight: number = srcDocView.props.PanelHeight();
+                const newPanX = NumCast(targetDoc.x) + NumCast(layoutdoc._width) / 2;
+                const newPanY = NumCast(targetDoc.y) + NumCast(layoutdoc._height) / 2;
+                const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+                srcContext._panX = newPanX + (vfLeft + (vfWidth / 2));
+                srcContext._panY = newPanY + (vfTop + (vfHeight / 2));
+                srcContext._viewScale = newScale;
+            }
+        }
+        // Case 2: document is the containing collection
+        if (docView && !srcContext) {
+            const panelWidth: number = docView.props.PanelWidth();
+            const panelHeight: number = docView.props.PanelHeight();
+            const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+            targetDoc._panX = vfLeft + (vfWidth / 2);
+            targetDoc._panY = vfTop + (vfWidth / 2);
+            targetDoc._viewScale = newScale;
+        }
+        const resize = document.getElementById('resizable');
+        if (resize) {
+            resize.style.width = vfWidth + 'px';
+            resize.style.height = vfHeight + 'px';
+            resize.style.top = vfTop + 'px';
+            resize.style.left = vfLeft + 'px';
+        }
+    }
+
+    /**
+     * For 'Hide Before' and 'Hide After' buttons making sure that
+     * they are hidden each time the presentation is updated.
+     */
+    @action
+    onHideDocument = () => {
+        this.childDocs.forEach((doc, index) => {
+            const curDoc = Cast(doc, Doc, null);
+            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+            if (tagDoc) tagDoc.opacity = 1;
+            const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc);
+            const curInd: number = itemIndexes.indexOf(index);
+            if (tagDoc === this.layoutDoc.presCollection) { tagDoc.opacity = 1; }
+            else {
+                if (itemIndexes.length > 1 && curDoc.presHideBefore && curInd !== 0) { }
+                else if (curDoc.presHideBefore) {
+                    if (index > this.itemIndex) {
+                        tagDoc.opacity = 0;
+                    } else if (!curDoc.presHideAfter) {
+                        tagDoc.opacity = 1;
+                    }
+                }
+                if (itemIndexes.length > 1 && curDoc.presHideAfter && curInd !== (itemIndexes.length - 1)) { }
+                else if (curDoc.presHideAfter) {
+                    if (index < this.itemIndex) {
+                        tagDoc.opacity = 0;
+                    } else if (!curDoc.presHideBefore) {
+                        tagDoc.opacity = 1;
+                    }
+                }
+            }
+        });
+    }
+
+
+
+    //The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc
+    @action
+    startAutoPres = (startSlide: number) => {
+        this.updateCurrentPresentation();
+        let activeItem: Doc = this.activeItem;
+        let targetDoc: Doc = this.targetDoc;
+        let duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
+        const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms));
+        const load = async () => { // Wrap the loop into an async function for this to work
+            for (var i = startSlide; i < this.childDocs.length; i++) {
+                activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+                targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
+                duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
+                if (duration < 100) { duration = 2500; }
+                if (NumCast(targetDoc.lastFrame) > 0) {
+                    for (var f = 0; f < NumCast(targetDoc.lastFrame); f++) {
+                        await timer(duration / NumCast(targetDoc.lastFrame));
+                        this.next();
+                    }
+                }
+
+                await timer(duration); this.next(); // then the created Promise can be awaited
+                if (i === this.childDocs.length - 1) {
+                    setTimeout(() => {
+                        clearTimeout(this._presTimer);
+                        if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = PresStatus.Manual;
+                        else if (this.layoutDoc.presLoop) this.startAutoPres(0);
+                    }, duration);
+                }
+            }
+        };
+        this.layoutDoc.presStatus = PresStatus.Autoplay;
+        this.startPresentation(startSlide);
+        this.gotoDocument(startSlide, activeItem);
+        load();
+    }
+
+    @action
+    pauseAutoPres = () => {
+        if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
+            if (this._presTimer) clearTimeout(this._presTimer);
+            this.layoutDoc.presStatus = PresStatus.Manual;
+            this.layoutDoc.presLoop = false;
+            this.childDocs.forEach(this.stopTempMedia);
+        }
+    }
+
+    //The function that resets the presentation by removing every action done by it. It also
+    //stops the presentaton.
+    resetPresentation = () => {
+        this.rootDoc._itemIndex = 0;
+        this.childDocs.map(doc => Cast(doc.presentationTargetDoc, Doc, null)).filter(doc => doc instanceof Doc).forEach(doc => {
+            try {
+                doc.opacity = 1;
+            } catch (e) {
+                console.log("Reset presentation error: ", e);
+            }
+        });
+    }
+
+    @action togglePath = (srcContext: Doc, off?: boolean) => {
+        if (off) {
+            this._pathBoolean = false;
+            srcContext.presPathView = false;
+        } else {
+            runInAction(() => this._pathBoolean = !this._pathBoolean);
+            srcContext.presPathView = this._pathBoolean;
+        }
+    }
+
+    @action toggleExpandMode = () => {
+        runInAction(() => this._expandBoolean = !this._expandBoolean);
+        this.rootDoc.expandBoolean = this._expandBoolean;
+        this.childDocs.forEach((doc) => {
+            doc.presExpandInlineButton = this._expandBoolean;
+        });
+    }
+
+    /**
+     * The function that starts the presentation at the given index, also checking if actions should be applied
+     * directly at start.
+     * @param startIndex: index that the presentation will start at
+     */
+    startPresentation = (startIndex: number) => {
+        this.updateCurrentPresentation();
+        this.childDocs.map(doc => {
+            const tagDoc = doc.presentationTargetDoc as Doc;
+            if (doc.presHideBefore && this.childDocs.indexOf(doc) > startIndex) {
+                tagDoc.opacity = 0;
+            }
+            if (doc.presHideAfter && this.childDocs.indexOf(doc) < startIndex) {
+                tagDoc.opacity = 0;
+            }
+        });
+    }
+
+    /**
+     * The method called to open the presentation as a minimized view
+     */
+    @action
+    updateMinimize = () => {
+        const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc);
+        if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
+            console.log("case 1");
+            this.layoutDoc.presStatus = PresStatus.Edit;
+            Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
+            CollectionDockingView.AddSplit(this.rootDoc, "right");
+        } else if (this.layoutDoc.context && docView) {
+            console.log("case 2");
+            this.layoutDoc.presStatus = PresStatus.Edit;
+            clearTimeout(this._presTimer);
+            const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+            this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250);
+            this.rootDoc.y = pt[1] + 10;
+            this.rootDoc._height = 35;
+            this.rootDoc._width = 250;
+            docView.props.removeDocument?.(this.layoutDoc);
+            Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
+        } else {
+            console.log("case 3");
+            // TODO glr: fix this case
+        }
+    }
+
+    /**
+     * Called when the user changes the view type
+     * Either 'List' (stacking) or 'Slides' (carousel)
+     */
+    // @undoBatch
+    viewChanged = action((e: React.ChangeEvent) => {
+        //@ts-ignore
+        const viewType = e.target.selectedOptions[0].value as CollectionViewType;
+        // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here
+        viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined);
+        this.rootDoc._viewType = viewType;
+        if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 0;
+    });
+
+    /**
+     * Called when the user changes the view type
+     * Either 'List' (stacking) or 'Slides' (carousel)
+     */
+    // @undoBatch
+    mediaStopChanged = action((e: React.ChangeEvent) => {
+        const activeItem: Doc = this.activeItem;
+        //@ts-ignore
+        const stopDoc = e.target.selectedOptions[0].value as string;
+        const stopDocIndex: number = Number(stopDoc[0]);
+        activeItem.mediaStopDoc = stopDocIndex;
+        if (this.childDocs[stopDocIndex - 1].mediaStopTriggerList) {
+            const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
+            list.push(activeItem);
+            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
+            console.log(list);
+        } else {
+            this.childDocs[stopDocIndex - 1].mediaStopTriggerList = new List<Doc>();
+            const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
+            list.push(activeItem);
+            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
+            console.log(list);
+        }
+    });
+
+
+    setMovementName = action((movement: any, activeItem: Doc): string => {
+        let output: string = 'none';
+        switch (movement) {
+            case PresMovement.Zoom: output = 'Pan & Zoom'; break; //Pan and zoom
+            case PresMovement.Pan: output = 'Pan'; break; //Pan
+            case PresMovement.Jump: output = 'Jump cut'; break; //Jump Cut
+            case PresMovement.None: output = 'None'; break; //None
+            default: output = 'Zoom'; activeItem.presMovement = 'zoom'; break; //default set as zoom
+        }
+        return output;
+    });
+
+    whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isChildActive = isActive));
+    // For dragging documents into the presentation trail
+    addDocumentFilter = (docs: Doc[]) => {
+        docs.forEach((doc, i) => {
+            if (doc.presentationTargetDoc) return true;
+            if (doc.type === DocumentType.LABEL) {
+                const audio = Cast(doc.annotationOn, Doc, null);
+                if (audio) {
+                    audio.mediaStart = "manual";
+                    audio.mediaStop = "manual";
+                    audio.presStartTime = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
+                    audio.presEndTime = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
+                    audio.presDuration = audio.presStartTime - audio.presEndTime;
+                    TabDocView.PinDoc(audio, { audioRange: true });
+                    setTimeout(() => this.removeDocument(doc), 0);
+                    return false;
+                }
+            } else {
+                if (!doc.aliasOf) {
+                    const original = Doc.MakeAlias(doc);
+                    TabDocView.PinDoc(original);
+                    setTimeout(() => this.removeDocument(doc), 0);
+                    return false;
+                } else {
+                    if (!doc.presentationTargetDoc) doc.title = doc.title + " - Slide";
+                    doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
+                    doc.presMovement = PresMovement.Zoom;
+                    if (this._expandBoolean) doc.presExpandInlineButton = true;
+                }
+            }
+        });
+        return true;
+    }
+    childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement;
+    removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
+    getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
+    panelHeight = () => this.props.PanelHeight() - 40;
+    isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
+        (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
+
+    /**
+     * For sorting the array so that the order is maintained when it is dropped.
+     */
+    @action
+    sortArray = (): Doc[] => {
+        return this.childDocs.filter(doc => this._selectedArray.has(doc));
+    }
+
+    /**
+     * Method to get the list of selected items in the order in which they have been selected
+     */
+    @computed get listOfSelected() {
+        const list = Array.from(this._selectedArray.keys()).map((doc: Doc, index: any) => {
+            const curDoc = Cast(doc, Doc, null);
+            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+            if (curDoc && curDoc === this.activeItem) return <div key={index} className="selectedList-items"><b>{index + 1}.  {curDoc.title}</b></div>;
+            else if (tagDoc) return <div key={index} className="selectedList-items">{index + 1}.  {curDoc.title}</div>;
+            else if (curDoc) return <div key={index} className="selectedList-items">{index + 1}.  {curDoc.title}</div>;
+        });
+        return list;
+    }
+
+    @action
+    selectPres = () => {
+        const presDocView = DocumentManager.Instance.getDocumentView(this.rootDoc);
+        presDocView && SelectionManager.SelectView(presDocView, false);
+    }
+
+    //Regular click
+    @action
+    selectElement = async (doc: Doc) => {
+        const context = Cast(doc.context, Doc, null);
+        this.gotoDocument(this.childDocs.indexOf(doc), this.activeItem);
+        if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
+        else this.updateCurrentPresentation(context);
+
+        if (this.activeItem.setPosition &&
+            this.activeItem.y !== undefined &&
+            this.activeItem.x !== undefined &&
+            this.targetDoc.x !== undefined &&
+            this.targetDoc.y !== undefined) {
+            const timer = (ms: number) => new Promise(res => this._presTimer = setTimeout(res, ms));
+            const time = 10;
+            const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y);
+            const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x);
+
+            for (let i = 0; i < time; i++) {
+                this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time;
+                this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time;
+                await timer(0.1);
+            }
+        }
+    }
+
+    //Command click
+    @action
+    multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
+        if (!this._selectedArray.has(doc)) {
+            this._selectedArray.set(doc, undefined);
+            this._eleArray.push(ref);
+            this._dragArray.push(drag);
+        } else {
+            this._selectedArray.delete(doc);
+            this.removeFromArray(this._eleArray, doc);
+            this.removeFromArray(this._dragArray, doc);
+        }
+        this.selectPres();
+    }
+
+    removeFromArray = (arr: any[], val: any) => {
+        const index: number = arr.indexOf(val);
+        const ret: any[] = arr.splice(index, 1);
+        arr = ret;
+    }
+
+    //Shift click
+    @action
+    shiftSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
+        this._selectedArray.clear();
+        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+        if (this.activeItem) {
+            for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) {
+                this._selectedArray.set(this.childDocs[i], undefined);
+                this._eleArray.push(ref);
+                this._dragArray.push(drag);
+            }
+        }
+        this.selectPres();
+    }
+
+    //regular click
+    @action
+    regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean) => {
+        this._selectedArray.clear();
+        this._selectedArray.set(doc, undefined);
+        this._eleArray.splice(0, this._eleArray.length, ref);
+        this._dragArray.splice(0, this._dragArray.length, drag);
+        focus && this.selectElement(doc);
+        this.selectPres();
+    }
+
+    modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => {
+        if (cmdClick) this.multiSelect(doc, ref, drag);
+        else if (shiftClick) this.shiftSelect(doc, ref, drag);
+        else this.regularSelect(doc, ref, drag, focus);
+    }
+
+    static keyEventsWrapper = (e: KeyboardEvent) => {
+        PresBox.Instance.keyEvents(e);
+    }
+
+    // Key for when the presentaiton is active
+    @action
+    keyEvents = (e: KeyboardEvent) => {
+        if (e.target instanceof HTMLInputElement) return;
+        let handled = false;
+        const anchorNode = document.activeElement as HTMLDivElement;
+        if (anchorNode && anchorNode.className?.includes("lm_title")) return;
+        switch (e.key) {
+            case "Backspace":
+                if (this.layoutDoc.presStatus === "edit") {
+                    undoBatch(action(() => {
+                        for (const doc of Array.from(this._selectedArray.keys())) {
+                            this.removeDocument(doc);
+                        }
+                        this._selectedArray.clear();
+                        this._eleArray.length = 0;
+                        this._dragArray.length = 0;
+                    }))();
+                    handled = true;
+                }
+                break;
+            case "Escape":
+                if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { this.updateMinimize(); }
+                else if (this.layoutDoc.presStatus === "edit") { this._selectedArray.clear(); this._eleArray.length = this._dragArray.length = 0; }
+                else this.layoutDoc.presStatus = "edit";
+                if (this._presTimer) clearTimeout(this._presTimer);
+                handled = true;
+                break;
+            case "Down": case "ArrowDown":
+            case "Right": case "ArrowRight":
+                if (e.shiftKey && this.itemIndex < this.childDocs.length - 1) { // TODO: update to work properly
+                    this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) + 1;
+                    this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
+                } else {
+                    this.next();
+                    if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
+                }
+                handled = true;
+                break;
+            case "Up": case "ArrowUp":
+            case "Left": case "ArrowLeft":
+                if (e.shiftKey && this.itemIndex !== 0) { // TODO: update to work properly
+                    this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) - 1;
+                    this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
+                } else {
+                    this.back();
+                    if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
+                }
+                handled = true;
+                break;
+            case "Spacebar": case " ":
+                if (this.layoutDoc.presStatus === PresStatus.Manual) this.startAutoPres(this.itemIndex);
+                else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
+                handled = true;
+                break;
+            case "a":
+                if ((e.metaKey || e.altKey) && this.layoutDoc.presStatus === "edit") {
+                    this._selectedArray.clear();
+                    this.childDocs.forEach(doc => this._selectedArray.set(doc, undefined));
+                    handled = true;
+                }
+            default:
+                break;
+        }
+        if (handled) {
+            e.stopPropagation();
+            e.preventDefault();
+        }
+    }
+
+    /**
+     * 
+     */
+    @action
+    viewPaths = () => {
+        const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
+        if (srcContext) {
+            this.togglePath(srcContext);
+        }
+    }
+
+    getAllIndexes = (arr: Doc[], val: Doc): number[] => {
+        const indexes = [];
+        for (let i = 0; i < arr.length; i++) {
+            arr[i] === val && indexes.push(i);
+        }
+        return indexes;
+    }
+
+    // Adds the index in the pres path graphically
+    @computed get order() {
+        const order: JSX.Element[] = [];
+        const docs: Doc[] = [];
+        const presCollection = Cast(this.rootDoc.presCollection, Doc, null);
+        const dv = DocumentManager.Instance.getDocumentView(presCollection);
+        this.childDocs.filter(doc => Cast(doc.presentationTargetDoc, Doc, null)).forEach((doc, index) => {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            const srcContext = Cast(tagDoc.context, Doc, null);
+            const width = NumCast(tagDoc._width) / 10;
+            const height = Math.max(NumCast(tagDoc._height) / 10, 15);
+            const edge = Math.max(width, height);
+            const fontSize = edge * 0.8;
+            const gap = 2;
+            if (presCollection === srcContext) {
+                // Case A: Document is contained within the collection
+                if (docs.includes(tagDoc)) {
+                    const prevOccurances: number = this.getAllIndexes(docs, tagDoc).length;
+                    docs.push(tagDoc);
+                    order.push(
+                        <div className="pathOrder"
+                            key={tagDoc.id + 'pres' + index}
+                            style={{ top: NumCast(tagDoc.y) + (prevOccurances * (edge + gap) - (edge / 2)), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
+                            onClick={() => this.selectElement(doc)}>
+                            <div className="pathOrder-frame">{index + 1}</div>
+                        </div>);
+                } else {
+                    docs.push(tagDoc);
+                    order.push(
+                        <div className="pathOrder"
+                            key={tagDoc.id + 'pres' + index}
+                            style={{ top: NumCast(tagDoc.y) - (edge / 2), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
+                            onClick={() => this.selectElement(doc)}>
+                            <div className="pathOrder-frame">{index + 1}</div>
+                        </div>);
+                }
+            } else if (doc.presPinView && presCollection === tagDoc && dv) {
+                // Case B: Document is presPinView and is presCollection
+                const scale: number = 1 / NumCast(doc.presPinViewScale);
+                const height: number = dv.props.PanelHeight() * scale;
+                const width: number = dv.props.PanelWidth() * scale;
+                const indWidth = width / 10;
+                const indHeight = Math.max(height / 10, 15);
+                const indEdge = Math.max(indWidth, indHeight);
+                const indFontSize = indEdge * 0.8;
+                const xLoc: number = NumCast(doc.presPinViewX) - (width / 2);
+                const yLoc: number = NumCast(doc.presPinViewY) - (height / 2);
+                docs.push(tagDoc);
+                order.push(
+                    <>
+                        <div className="pathOrder"
+                            key={tagDoc.id + 'pres' + index}
+                            style={{ top: yLoc - (indEdge / 2), left: xLoc - (indEdge / 2), width: indEdge, height: indEdge, fontSize: indFontSize }}
+                            onClick={() => this.selectElement(doc)}
+                        >
+                            <div className="pathOrder-frame">{index + 1}</div>
+                        </div>
+                        <div className="pathOrder-presPinView" style={{ top: yLoc, left: xLoc, width: width, height: height, borderWidth: indEdge / 10 }}></div>
+                    </>);
+            }
+        });
+        return order;
+    }
+
+    /**
+     * Method called for viewing paths which adds a single line with
+     * points at the center of each document added.
+     * Design choice: When this is called it sets _fitToBox as true so the
+     * user can have an overview of all of the documents in the collection.
+     * (Design needed for when documents in presentation trail are in another
+     * collection)
+     */
+    @computed get paths() {
+        let pathPoints = "";
+        const presCollection = Cast(this.rootDoc.presCollection, Doc, null);
+        this.childDocs.forEach((doc, index) => {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            const srcContext = Cast(tagDoc?.context, Doc, null);
+            if (tagDoc && presCollection === srcContext) {
+                const n1x = NumCast(tagDoc.x) + (NumCast(tagDoc._width) / 2);
+                const n1y = NumCast(tagDoc.y) + (NumCast(tagDoc._height) / 2);
+                if (index = 0) pathPoints = n1x + "," + n1y;
+                else pathPoints = pathPoints + " " + n1x + "," + n1y;
+            } else if (doc.presPinView && presCollection === tagDoc) {
+                const n1x = NumCast(doc.presPinViewX);
+                const n1y = NumCast(doc.presPinViewY);
+                if (index = 0) pathPoints = n1x + "," + n1y;
+                else pathPoints = pathPoints + " " + n1x + "," + n1y;
+            }
+        });
+        return (<polyline
+            points={pathPoints}
+            style={{
+                opacity: 1,
+                stroke: "#69a6db",
+                strokeWidth: 5,
+                strokeDasharray: '10 5',
+                boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
+            }}
+            fill="none"
+            markerStart="url(#markerArrow)"
+            markerMid="url(#markerSquare)"
+            markerEnd="url(#markerSquareFilled)"
+        />);
+    }
+
+    // Converts seconds to ms and updates presTransition
+    setTransitionTime = (number: String, change?: number) => {
+        let timeInMS = Number(number) * 1000;
+        if (change) timeInMS += change;
+        if (timeInMS < 100) timeInMS = 100;
+        if (timeInMS > 10000) timeInMS = 10000;
+        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presTransition = timeInMS);
+    }
+
+    // Converts seconds to ms and updates presDuration
+    setDurationTime = (number: String, change?: number) => {
+        let timeInMS = Number(number) * 1000;
+        if (change) timeInMS += change;
+        if (timeInMS < 100) timeInMS = 100;
+        if (timeInMS > 20000) timeInMS = 20000;
+        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presDuration = timeInMS);
+    }
+
+    /**
+     * When the movement dropdown is changes
+     */
+    @undoBatch
+    updateMovement = action((movement: any, all?: boolean) => {
+        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
+        array.forEach((doc) => {
+            switch (movement) {
+                case PresMovement.Zoom: //Pan and zoom
+                    doc.presMovement = PresMovement.Zoom;
+                    break;
+                case PresMovement.Pan: //Pan
+                    doc.presMovement = PresMovement.Pan;
+                    break;
+                case PresMovement.Jump: //Jump Cut
+                    doc.presJump = true;
+                    doc.presMovement = PresMovement.Jump;
+                    break;
+                case PresMovement.None: default:
+                    doc.presMovement = PresMovement.None;
+                    break;
+            }
+        });
+    });
+
+    @undoBatch
+    @action
+    updateHideBefore = (activeItem: Doc) => {
+        activeItem.presHideBefore = !activeItem.presHideBefore;
+        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideBefore = activeItem.presHideBefore);
+    }
+
+    @undoBatch
+    @action
+    updateHideAfter = (activeItem: Doc) => {
+        activeItem.presHideAfter = !activeItem.presHideAfter;
+        Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideAfter = activeItem.presHideAfter);
+    }
+
+    @undoBatch
+    @action
+    updateOpenDoc = (activeItem: Doc) => {
+        activeItem.openDocument = !activeItem.openDocument;
+        Array.from(this._selectedArray.keys()).forEach((doc) => {
+            doc.openDocument = activeItem.openDocument;
+        });
+    }
+
+    @undoBatch
+    @action
+    updateEffectDirection = (effect: any, all?: boolean) => {
+        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
+        array.forEach((doc) => {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            switch (effect) {
+                case PresEffect.Left:
+                    tagDoc.presEffectDirection = PresEffect.Left;
+                    break;
+                case PresEffect.Right:
+                    tagDoc.presEffectDirection = PresEffect.Right;
+                    break;
+                case PresEffect.Top:
+                    tagDoc.presEffectDirection = PresEffect.Top;
+                    break;
+                case PresEffect.Bottom:
+                    tagDoc.presEffectDirection = PresEffect.Bottom;
+                    break;
+                case PresEffect.Center: default:
+                    tagDoc.presEffectDirection = PresEffect.Center;
+                    break;
+            }
+        });
+    }
+
+    @undoBatch
+    @action
+    updateEffect = (effect: any, all?: boolean) => {
+        const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
+        array.forEach((doc) => {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            switch (effect) {
+                case PresEffect.Bounce:
+                    tagDoc.presEffect = PresEffect.Bounce;
+                    break;
+                case PresEffect.Fade:
+                    tagDoc.presEffect = PresEffect.Fade;
+                    break;
+                case PresEffect.Flip:
+                    tagDoc.presEffect = PresEffect.Flip;
+                    break;
+                case PresEffect.Roll:
+                    tagDoc.presEffect = PresEffect.Roll;
+                    break;
+                case PresEffect.Rotate:
+                    tagDoc.presEffect = PresEffect.Rotate;
+                    break;
+                case PresEffect.None: default:
+                    tagDoc.presEffect = PresEffect.None;
+                    break;
+            }
+        });
+    }
+
+    _batch: UndoManager.Batch | undefined = undefined;
+
+    @computed get transitionDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const type = targetDoc.type;
+        const isPresCollection: boolean = (targetDoc === this.layoutDoc.presCollection);
+        const isPinWithView: boolean = BoolCast(activeItem.presPinView);
+        if (activeItem && targetDoc) {
+            const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
+            let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
+            if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
+            const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
+            activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
+            return (
+                <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === PresStatus.Edit ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = false; this.openEffectDropdown = false; })}>
+                    <div className="ribbon-box">
+                        Movement
+                        {isPresCollection || (isPresCollection && isPinWithView) ?
+                            <div className="ribbon-property" style={{ marginLeft: 0, height: 25, textAlign: 'left', paddingLeft: 5, paddingRight: 5, fontSize: 10 }}>
+                                {this.scrollable ? "Scroll to pinned view" : !isPinWithView ? "No movement" : "Pan & Zoom to pinned view"}
+                            </div>
+                            :
+                            <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                                {this.setMovementName(activeItem.presMovement, activeItem)}
+                                <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={"angle-down"} />
+                                <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}>
+                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.None ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.None)}>None</div>
+                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Zoom ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Zoom)}>Pan {"&"} Zoom</div>
+                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Pan ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Pan)}>Pan</div>
+                                    <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Jump ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Jump)}>Jump cut</div>
+                                </div>
+                            </div>
+                        }
+                        <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "inline-flex" : "none" }}>
+                            <div className="presBox-subheading">Movement Speed</div>
+                            <div className="ribbon-property">
+                                <input className="presBox-input"
+                                    type="number" value={transitionSpeed}
+                                    onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
+                            </div>
+                            <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), 1000))}>
+                                    <FontAwesomeIcon icon={"caret-up"} />
+                                </div>
+                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), -1000))}>
+                                    <FontAwesomeIcon icon={"caret-down"} />
+                                </div>
+                            </div>
+                        </div>
+                        <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed}
+                            className={`toolbar-slider ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}
+                            id="toolbar-slider"
+                            onPointerDown={() => this._batch = UndoManager.StartBatch("presTransition")}
+                            onPointerUp={() => this._batch?.end()}
+                            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                e.stopPropagation();
+                                this.setTransitionTime(e.target.value);
+                            }} />
+                        <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                            <div className="slider-text">Fast</div>
+                            <div className="slider-text">Medium</div>
+                            <div className="slider-text">Slow</div>
+                        </div>
+                    </div>
+                    <div className="ribbon-box">
+                        Visibility {"&"} Duration
+                        <div className="ribbon-doubleButton">
+                            {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideBefore ? "active" : ""}`} onClick={() => this.updateHideBefore(activeItem)}>Hide before</div></Tooltip>}
+                            {isPresCollection ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideAfter ? "active" : ""}`} onClick={() => this.updateHideAfter(activeItem)}>Hide after</div></Tooltip>}
+                            <Tooltip title={<><div className="dash-tooltip">{"Open in lightbox view"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? Colors.LIGHT_BLUE : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Lightbox</div></Tooltip>
+                        </div>
+                        {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <>
+                            <div className="ribbon-doubleButton" >
+                                <div className="presBox-subheading">Slide Duration</div>
+                                <div className="ribbon-property">
+                                    <input className="presBox-input"
+                                        type="number" value={duration}
+                                        onChange={action((e) => this.setDurationTime(e.target.value))} /> s
+                            </div>
+                                <div className="ribbon-propertyUpDown">
+                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
+                                        <FontAwesomeIcon icon={"caret-up"} />
+                                    </div>
+                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), -1000))}>
+                                        <FontAwesomeIcon icon={"caret-down"} />
+                                    </div>
+                                </div>
+                            </div>
+                            <input type="range" step="0.1" min="0.1" max="20" value={duration}
+                                style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }}
+                                className={"toolbar-slider"} id="duration-slider"
+                                onPointerDown={() => { this._batch = UndoManager.StartBatch("presDuration"); }}
+                                onPointerUp={() => { if (this._batch) this._batch.end(); }}
+                                onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }}
+                            />
+                            <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}>
+                                <div className="slider-text">Short</div>
+                                <div className="slider-text">Medium</div>
+                                <div className="slider-text">Long</div>
+                            </div>
+                        </>}
+                    </div>
+                    {isPresCollection ? (null) : <div className="ribbon-box">
+                        Effects
+                        <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown; })} style={{ borderBottomLeftRadius: this.openEffectDropdown ? 0 : 5, border: this.openEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            {effect}
+                            <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={"angle-down"} />
+                            <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.None || !targetDoc.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Flip ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Rotate ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Bounce ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Roll ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
+                            </div>
+                        </div>
+                        <div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
+                            <div className="presBox-subheading" >Effect direction</div>
+                            <div className="ribbon-property">
+                                {this.effectDirection}
+                            </div>
+                        </div>
+                        <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${Colors.LIGHT_BLUE}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip>
+                        </div>
+                    </div>}
+                    <div className="ribbon-final-box">
+                        <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}>
+                            Apply to all
+                        </div>
+                    </div>
+                </div >
+            );
+        }
+    }
+
+    @computed get effectDirection(): string {
+        let effect = '';
+        switch (this.targetDoc.presEffectDirection) {
+            case 'left': effect = "Enter from left"; break;
+            case 'right': effect = "Enter from right"; break;
+            case 'top': effect = "Enter from top"; break;
+            case 'bottom': effect = "Enter from bottom"; break;
+            default: effect = "Enter from center"; break;
+        }
+        return effect;
+    }
+
+    @undoBatch
+    @action
+    applyTo = (array: Doc[]) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        this.updateMovement(activeItem.presMovement, true);
+        this.updateEffect(targetDoc.presEffect, true);
+        this.updateEffectDirection(targetDoc.presEffectDirection, true);
+        array.forEach((doc) => {
+            const curDoc = Cast(doc, Doc, null);
+            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+            if (tagDoc && targetDoc) {
+                curDoc.presTransition = activeItem.presTransition;
+                curDoc.presDuration = activeItem.presDuration;
+                curDoc.presHideBefore = activeItem.presHideBefore;
+                curDoc.presHideAfter = activeItem.presHideAfter;
+            }
+        });
+    }
+
+    @computed get presPinViewOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: "auto", width: 16, filter: 'invert(1)' }} />;
+        return (
+            <>
+                {this.panable || this.scrollable || this.targetDoc.type === DocumentType.COMPARISON ? 'Pinned view' : (null)}
+                <div className="ribbon-doubleButton">
+                    <Tooltip title={<><div className="dash-tooltip">{activeItem.presPinView ? "Turn off pin with view" : "Turn on pin with view"}</div></>}><div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? Colors.LIGHT_BLUE : "" }}
+                        onClick={() => {
+                            activeItem.presPinView = !activeItem.presPinView;
+                            targetDoc.presPinView = activeItem.presPinView;
+                            if (activeItem.presPinView) {
+                                if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking) {
+                                    const scroll = targetDoc._scrollTop;
+                                    activeItem.presPinView = true;
+                                    activeItem.presPinViewScroll = scroll;
+                                } else if (targetDoc.type === DocumentType.VID) {
+                                    activeItem.presPinTimecode = targetDoc._currentTimecode;
+                                } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) {
+                                    const x = targetDoc._panX;
+                                    const y = targetDoc._panY;
+                                    const scale = targetDoc._viewScale;
+                                    activeItem.presPinView = true;
+                                    activeItem.presPinViewX = x;
+                                    activeItem.presPinViewY = y;
+                                    activeItem.presPinViewScale = scale;
+                                } else if (targetDoc.type === DocumentType.COMPARISON) {
+                                    const width = targetDoc._clipWidth;
+                                    activeItem.presPinClipWidth = width;
+                                    activeItem.presPinView = true;
+                                }
+                            }
+                        }}>{presPinWithViewIcon}</div></Tooltip>
+                    {activeItem.presPinView ? <Tooltip title={<><div className="dash-tooltip">{"Update the pinned view with the view of the selected document"}</div></>}><div className="ribbon-button"
+                        onClick={() => {
+                            if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
+                                const scroll = targetDoc._scrollTop;
+                                activeItem.presPinViewScroll = scroll;
+                            } else if (targetDoc.type === DocumentType.VID) {
+                                activeItem.presPinTimecode = targetDoc._currentTimecode;
+                            } else if (targetDoc.type === DocumentType.COMPARISON) {
+                                const clipWidth = targetDoc._clipWidth;
+                                activeItem.presPinClipWidth = clipWidth;
+                            } else {
+                                const x = targetDoc._panX;
+                                const y = targetDoc._panY;
+                                const scale = targetDoc._viewScale;
+                                activeItem.presPinViewX = x;
+                                activeItem.presPinViewY = y;
+                                activeItem.presPinViewScale = scale;
+                            }
+                        }}>Update</div></Tooltip> : (null)}
+                </div>
+            </>
+        );
+    }
+
+    @computed get panOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        return (
+            <>
+                {this.panable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
+                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+                        <div className="presBox-subheading">Pan X</div>
+                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                            <input className="presBox-input"
+                                style={{ textAlign: 'left', width: 50 }}
+                                type="number" value={NumCast(activeItem.presPinViewX)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewX = Number(val); })} />
+                        </div>
+                    </div>
+                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+                        <div className="presBox-subheading">Pan Y</div>
+                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                            <input className="presBox-input"
+                                style={{ textAlign: 'left', width: 50 }}
+                                type="number" value={NumCast(activeItem.presPinViewY)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewY = Number(val); })} />
+                        </div>
+                    </div>
+                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+                        <div className="presBox-subheading">Scale</div>
+                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                            <input className="presBox-input"
+                                style={{ textAlign: 'left', width: 50 }}
+                                type="number" value={NumCast(activeItem.presPinViewScale)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
+                        </div>
+                    </div>
+                </div> : (null)}
+            </>
+        );
+    }
+
+    @computed get scrollOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        return (
+            <>
+                {this.scrollable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
+                    <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+                        <div className="presBox-subheading">Scroll</div>
+                        <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                            <input className="presBox-input"
+                                style={{ textAlign: 'left', width: 50 }}
+                                type="number" value={NumCast(activeItem.presPinViewScroll)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
+                        </div>
+                    </div>
+                </div> : (null)}
+            </>
+        );
+    }
+
+    @computed get mediaStopSlides() {
+        const activeItem: Doc = this.activeItem;
+        const list = this.childDocs.map((doc, i) => {
+            if (i > this.itemIndex) {
+                return (
+                    <option>{i + 1}. {doc.title}</option>
+                );
+            }
+        });
+        return (
+            list
+        );
+    }
+
+    @computed get mediaOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const duration = Math.round(NumCast(activeItem[`${Doc.LayoutFieldKey(activeItem)}-duration`]) * 10);
+        const mediaStopDocInd: number = NumCast(activeItem.mediaStopDoc);
+        const mediaStopDocStr: string = mediaStopDocInd ? mediaStopDocInd + ". " + this.childDocs[mediaStopDocInd - 1].title : "";
+        if (activeItem && targetDoc) {
+            return (
+                <div>
+                    <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+                        <div>
+                            <div className="ribbon-box">
+                                Start {"&"} End Time
+                                <div className={"slider-headers"}>
+                                    <div className="slider-block" >
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            Start time (s)
+                                        </div>
+                                        <div id={"startTime"} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                            <input className="presBox-input"
+                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
+                                                type="number" value={NumCast(activeItem.presStartTime)}
+                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
+                                            />
+                                        </div>
+                                    </div>
+                                    <div className="slider-block">
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            Duration (s)
+                                        </div>
+                                        <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}>
+                                            {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10}
+                                        </div>
+                                    </div>
+                                    <div className="slider-block">
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            End time (s)
+                                        </div>
+                                        <div id={"endTime"} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                            <input className="presBox-input"
+                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
+                                                type="number" value={NumCast(activeItem.presEndTime)}
+                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
+                                            />
+                                        </div>
+                                    </div>
+                                </div>
+                                <div className="multiThumb-slider">
+                                    <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presEndTime)}
+                                        style={{ gridColumn: 1, gridRow: 1 }}
+                                        className={`toolbar-slider ${"end"}`}
+                                        id="toolbar-slider"
+                                        onPointerDown={() => {
+                                            this._batch = UndoManager.StartBatch("presEndTime");
+                                            const endBlock = document.getElementById("endTime");
+                                            if (endBlock) {
+                                                endBlock.style.color = Colors.LIGHT_GRAY;
+                                                endBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            }
+                                        }}
+                                        onPointerUp={() => {
+                                            this._batch?.end();
+                                            const endBlock = document.getElementById("endTime");
+                                            if (endBlock) {
+                                                endBlock.style.color = Colors.BLACK;
+                                                endBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            }
+                                        }}
+                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                            e.stopPropagation();
+                                            activeItem.presEndTime = Number(e.target.value);
+                                        }} />
+                                    <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presStartTime)}
+                                        style={{ gridColumn: 1, gridRow: 1 }}
+                                        className={`toolbar-slider ${"start"}`}
+                                        id="toolbar-slider"
+                                        onPointerDown={() => {
+                                            this._batch = UndoManager.StartBatch("presStartTime");
+                                            const startBlock = document.getElementById("startTime");
+                                            if (startBlock) {
+                                                startBlock.style.color = Colors.LIGHT_GRAY;
+                                                startBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            }
+                                        }}
+                                        onPointerUp={() => {
+                                            this._batch?.end();
+                                            const startBlock = document.getElementById("startTime");
+                                            if (startBlock) {
+                                                startBlock.style.color = Colors.BLACK;
+                                                startBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            }
+                                        }}
+                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                            e.stopPropagation();
+                                            activeItem.presStartTime = Number(e.target.value);
+                                        }} />
+                                </div>
+                                <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                                    <div className="slider-text">0 s</div>
+                                    <div className="slider-text"></div>
+                                    <div className="slider-text">{duration / 10} s</div>
+                                </div>
+                            </div>
+                            <div className="ribbon-final-box">
+                                Playback
+                                <div className="presBox-subheading">Start playing:</div>
+                                <div className="presBox-radioButtons">
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStart = "manual"}
+                                            checked={activeItem.mediaStart === "manual"}
+                                        />
+                                        <div>On click</div>
+                                    </div>
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStart = "auto"}
+                                            checked={activeItem.mediaStart === "auto"}
+                                        />
+                                        <div>Automatically</div>
+                                    </div>
+                                </div>
+                                <div className="presBox-subheading">Stop playing:</div>
+                                <div className="presBox-radioButtons">
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStop = "manual"}
+                                            checked={activeItem.mediaStop === "manual"}
+                                        />
+                                        <div>At audio end time</div>
+                                    </div>
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStop = "auto"}
+                                            checked={activeItem.mediaStop === "auto"}
+                                        />
+                                        <div>On slide change</div>
+                                    </div>
+                                    {/* <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaStop = "afterSlide"}
+                                        checked={activeItem.mediaStop === "afterSlide"}
+                                    />
+                                    <div className="checkbox-dropdown">
+                                        After chosen slide
+                                        <select className="presBox-viewPicker"
+                                            style={{ opacity: activeItem.mediaStop === "afterSlide" && this.itemIndex !== this.childDocs.length - 1 ? 1 : 0.3 }}
+                                            onPointerDown={e => e.stopPropagation()}
+                                            onChange={this.mediaStopChanged}
+                                            value={mediaStopDocStr}>
+                                            {this.mediaStopSlides}
+                                        </select>
+                                    </div>
+                                </div> */}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div >
+            );
+        }
+    }
+
+    @computed get newDocumentToolbarDropdown() {
+        return (
+            <div>
+                <div className={'presBox-toolbar-dropdown'} style={{ display: this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+                    <div className="layout-container" style={{ height: 'max-content' }}>
+                        <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} />
+                        <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}>
+                            <div className="title">Title</div>
+                            <div className="subtitle">Subtitle</div>
+                        </div>
+                        <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}>
+                            <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
+                        </div>
+                        <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}>
+                            <div className="title" style={{ alignSelf: 'center' }}>Title</div>
+                            <div className="content">Text goes here</div>
+                        </div>
+                    </div>
+                </div>
+            </div >
+        );
+    }
+
+    @observable openLayouts: boolean = false;
+    @observable addFreeform: boolean = true;
+    @observable layout: string = "";
+    @observable title: string = "";
+
+    @computed get newDocumentDropdown() {
+        return (
+            <div>
+                <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+                    <div className="ribbon-box">
+                        Slide Title: <br></br>
+                        <input className="ribbon-textInput" placeholder="..." type="text" name="fname"
+                            onChange={(e) => {
+                                e.stopPropagation();
+                                e.preventDefault();
+                                runInAction(() => this.title = e.target.value);
+                            }}>
+                        </input>
+                    </div>
+                    <div className="ribbon-box">
+                        Choose type:
+                        <div className="ribbon-doubleButton">
+                            <div title="Text" className={'ribbon-toggle'} style={{ background: this.addFreeform ? "" : Colors.LIGHT_BLUE }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Text</div>
+                            <div title="Freeform" className={'ribbon-toggle'} style={{ background: this.addFreeform ? Colors.LIGHT_BLUE : "" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Freeform</div>
+                        </div>
+                    </div>
+                    <div className="ribbon-box" style={{ display: this.addFreeform ? "grid" : "none" }}>
+                        Preset layouts:
+                        <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}>
+                            <div className="layout" style={{ border: this.layout === 'blank' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'blank')} />
+                            <div className="layout" style={{ border: this.layout === 'title' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'title')}>
+                                <div className="title">Title</div>
+                                <div className="subtitle">Subtitle</div>
+                            </div>
+                            <div className="layout" style={{ border: this.layout === 'header' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'header')}>
+                                <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
+                            </div>
+                            <div className="layout" style={{ border: this.layout === 'content' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'content')}>
+                                <div className="title" style={{ alignSelf: 'center' }}>Title</div>
+                                <div className="content">Text goes here</div>
+                            </div>
+                            <div className="layout" style={{ border: this.layout === 'twoColumns' ? `solid 2px ${Colors.MEDIUM_BLUE}` : '' }} onClick={action(() => this.layout = 'twoColumns')}>
+                                <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div>
+                                <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div>
+                                <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div>
+                            </div>
+                        </div>
+                        <div className="open-layout" onClick={action(() => this.openLayouts = !this.openLayouts)}>
+                            <FontAwesomeIcon style={{ transition: 'all 0.3s', transform: this.openLayouts ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"caret-down"} size={"lg"} />
+                        </div>
+                    </div>
+                    <div className="ribbon-final-box">
+                        <div className={this.title !== "" && (this.addFreeform && this.layout !== "" || !this.addFreeform) ? "ribbon-final-button-hidden" : "ribbon-final-button"} onClick={() => this.createNewSlide(this.layout, this.title, this.addFreeform)}>
+                            Create New Slide
+                        </div>
+                    </div>
+                </div>
+            </div >
+        );
+    }
+
+    createNewSlide = (layout?: string, title?: string, freeform?: boolean) => {
+        let doc = undefined;
+        if (layout) doc = this.createTemplate(layout);
+        if (freeform && layout) doc = this.createTemplate(layout, title);
+        if (!freeform && !layout) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title });
+        if (doc) {
+            const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
+            const data = Cast(presCollection?.data, listSpec(Doc));
+            const presData = Cast(this.rootDoc.data, listSpec(Doc));
+            if (data && presData) {
+                data.push(doc);
+                TabDocView.PinDoc(doc);
+                this.gotoDocument(this.childDocs.length, this.activeItem);
+            } else {
+                this.props.addDocTab(doc, "add:right");
+            }
+        }
+    }
+
+    createTemplate = (layout: string, input?: string) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        let x = 0;
+        let y = 0;
+        if (activeItem && targetDoc) {
+            x = NumCast(targetDoc.x);
+            y = NumCast(targetDoc.y) + NumCast(targetDoc._height) + 20;
+        }
+        let doc = undefined;
+        const title = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 58, _fontSize: "24pt", });
+        const subtitle = Docs.Create.TextDocument("Click to change subtitle", { title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt" });
+        const header = Docs.Create.TextDocument("Click to change header", { title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt" });
+        const contentTitle = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt" });
+        const content = Docs.Create.TextDocument("Click to change text", { title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" });
+        const content1 = Docs.Create.TextDocument("Click to change text", { title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt" });
+        const content2 = Docs.Create.TextDocument("Click to change text", { title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" });
+        switch (layout) {
+            case 'blank':
+                doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, x: x, y: y });
+                break;
+            case 'title':
+                doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                break;
+            case 'header':
+                doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                break;
+            case 'content':
+                doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                break;
+            case 'twoColumns':
+                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                break;
+            default:
+                break;
+        }
+        return doc;
+    }
+
+    // Dropdown that appears when the user wants to begin presenting (either minimize or sidebar view)
+    @computed get presentDropdown() {
+        return (
+            <div className={`dropdown-play ${this.presentTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+                <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.updateMinimize(); this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); }))}>
+                    Mini-player
+                </div>
+                <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); this.gotoDocument(this.itemIndex, this.activeItem); }))}>
+                    Sidebar player
+                </div>
+            </div>
+        );
+    }
+
+    // Case in which the document has keyframes to navigate to next key frame
+    @action
+    nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => {
+        const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
+        const currentFrame = Cast(tagDoc._currentFrame, "number", null);
+        if (currentFrame === undefined) {
+            tagDoc._currentFrame = 0;
+            // CollectionFreeFormDocumentView.setupScroll(tagDoc, 0);
+            // CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+        }
+        // if (tagDoc.editScrollProgressivize) CollectionFreeFormDocumentView.updateScrollframe(tagDoc, currentFrame);
+        CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0, tagDoc);
+        tagDoc._currentFrame = Math.max(0, (currentFrame || 0) + 1);
+        tagDoc.lastFrame = Math.max(NumCast(tagDoc._currentFrame), NumCast(tagDoc.lastFrame));
+    }
+
+    @action
+    prevKeyframe = (tagDoc: Doc, actItem: Doc): void => {
+        const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
+        const currentFrame = Cast(tagDoc._currentFrame, "number", null);
+        if (currentFrame === undefined) {
+            tagDoc._currentFrame = 0;
+            // CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+        }
+        CollectionFreeFormDocumentView.gotoKeyframe(childDocs.slice());
+        tagDoc._currentFrame = Math.max(0, (currentFrame || 0) - 1);
+    }
+
+    /**
+     * Returns the collection type as a string for headers
+     */
+    @computed get stringType(): string {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        let type: string = '';
+        if (activeItem) {
+            switch (targetDoc.type) {
+                case DocumentType.PDF: type = "PDF"; break;
+                case DocumentType.RTF: type = "Text node"; break;
+                case DocumentType.COL: type = "Collection"; break;
+                case DocumentType.AUDIO: type = "Audio"; break;
+                case DocumentType.VID: type = "Video"; break;
+                case DocumentType.IMG: type = "Image"; break;
+                case DocumentType.WEB: type = "Web page"; break;
+                default: type = "Other node"; break;
+            }
+        }
+        return type;
+    }
+
+    @observable private openActiveColorPicker: boolean = false;
+    @observable private openViewedColorPicker: boolean = false;
+
+
+
+    @computed get progressivizeDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        if (activeItem && targetDoc) {
+            const activeFontColor = targetDoc["pres-text-color"] ? StrCast(targetDoc["pres-text-color"]) : "Black";
+            const viewedFontColor = targetDoc["pres-text-viewed-color"] ? StrCast(targetDoc["pres-text-viewed-color"]) : "Black";
+            return (
+                <div>
+                    <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
+                        <div className="ribbon-box">
+                            {this.stringType} selected
+                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
+                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeChild}>Contents</div>
+                                <div className="ribbon-toggle" style={{ opacity: activeItem.presProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editProgressivize}>Edit</div>
+                            </div>
+                            <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}>
+                                <div className="presBox-subheading">Active text color</div>
+                                <div className="ribbon-colorBox" style={{ backgroundColor: activeFontColor, height: 15, width: 15 }} onClick={action(() => { this.openActiveColorPicker = !this.openActiveColorPicker; })}>
+                                </div>
+                            </div>
+                            {this.activeColorPicker}
+                            <div className="ribbon-doubleButton" style={{ display: activeItem.presProgressivize ? "inline-flex" : "none" }}>
+                                <div className="presBox-subheading">Viewed font color</div>
+                                <div className="ribbon-colorBox" style={{ backgroundColor: viewedFontColor, height: 15, width: 15 }} onClick={action(() => this.openViewedColorPicker = !this.openViewedColorPicker)}>
+                                </div>
+                            </div>
+                            {this.viewedColorPicker}
+                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}>
+                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.zoomProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeZoom}>Zoom</div>
+                                <div className="ribbon-toggle" style={{ opacity: activeItem.zoomProgressivize ? 1 : 0.4, backgroundColor: activeItem.editZoomProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editZoomProgressivize}>Edit</div>
+                            </div>
+                            <div className="ribbon-doubleButton" style={{ borderTop: 'solid 1px darkgrey', display: targetDoc._viewType === "stacking" || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
+                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.scrollProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.progressivizeScroll}>Scroll</div>
+                                <div className="ribbon-toggle" style={{ opacity: activeItem.scrollProgressivize ? 1 : 0.4, backgroundColor: targetDoc.editScrollProgressivize ? Colors.LIGHT_BLUE : "" }} onClick={this.editScrollProgressivize}>Edit</div>
+                            </div>
+                        </div>
+                        <div className="ribbon-final-box">
+                            Frames
+                            <div className="ribbon-doubleButton">
+                                <div className="ribbon-frameSelector">
+                                    <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc, activeItem); }}>
+                                        <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
+                                    </div>
+                                    <div key="num" title="toggle view all" className="numKeyframe" style={{ color: targetDoc.keyFrameEditing ? "white" : "black", backgroundColor: targetDoc.keyFrameEditing ? Colors.MEDIUM_BLUE : Colors.LIGHT_BLUE }}
+                                        onClick={action(() => targetDoc.keyFrameEditing = !targetDoc.keyFrameEditing)} >
+                                        {NumCast(targetDoc._currentFrame)}
+                                    </div>
+                                    <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={e => { e.stopPropagation(); this.nextKeyframe(targetDoc, activeItem); }}>
+                                        <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
+                                    </div>
+                                </div>
+                                <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div className="ribbon-property">{NumCast(targetDoc.lastFrame)}</div></Tooltip>
+                            </div>
+                            <div className="ribbon-frameList">
+                                {this.frameListHeader}
+                                {this.frameList}
+                            </div>
+                            <div className="ribbon-toggle" style={{ height: 20, backgroundColor: Colors.LIGHT_BLUE }} onClick={() => console.log(" TODO: play frames")}>Play</div>
+                        </div>
+                    </div>
+                </div>
+            );
+        }
+    }
+
+    @undoBatch
+    @action
+    switchActive = (color: ColorState) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const val = String(color.hex);
+        targetDoc["pres-text-color"] = val;
+        return true;
+    }
+    @undoBatch
+    @action
+    switchPresented = (color: ColorState) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const val = String(color.hex);
+        targetDoc["pres-text-viewed-color"] = val;
+        return true;
+    }
+
+    @computed get activeColorPicker() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        return !this.openActiveColorPicker ? (null) : <SketchPicker onChange={this.switchActive}
+            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+                '#FFFFFF', '#f1efeb', 'transparent']}
+            color={StrCast(targetDoc["pres-text-color"])} />;
+    }
+
+    @computed get viewedColorPicker() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        return !this.openViewedColorPicker ? (null) : <SketchPicker onChange={this.switchPresented}
+            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+                '#FFFFFF', '#f1efeb', 'transparent']}
+            color={StrCast(targetDoc["pres-text-viewed-color"])} />;
+    }
+
+    @action
+    turnOffEdit = (paths?: boolean) => {
+        // Turn off paths
+        if (paths) {
+            const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
+            if (srcContext) this.togglePath(srcContext, true);
+        }
+        // Turn off the progressivize editors for each document
+        this.childDocs.forEach((doc) => {
+            doc.editSnapZoomProgressivize = false;
+            doc.editZoomProgressivize = false;
+            const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            if (targetDoc) {
+                targetDoc.editZoomProgressivize = false;
+                // targetDoc.editScrollProgressivize = false;
+            }
+        });
+    }
+
+    //Toggle whether the user edits or not
+    @action
+    editZoomProgressivize = (e: React.MouseEvent) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        if (!targetDoc.editZoomProgressivize) {
+            if (!activeItem.zoomProgressivize) activeItem.zoomProgressivize = true; targetDoc.zoomProgressivize = true;
+            targetDoc.editZoomProgressivize = true;
+            activeItem.editZoomProgressivize = true;
+        } else {
+            targetDoc.editZoomProgressivize = false;
+            activeItem.editZoomProgressivize = false;
+        }
+    }
+
+    //Toggle whether the user edits or not
+    @action
+    editScrollProgressivize = (e: React.MouseEvent) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        if (!targetDoc.editScrollProgressivize) {
+            if (!targetDoc.scrollProgressivize) { targetDoc.scrollProgressivize = true; activeItem.scrollProgressivize = true; }
+            targetDoc.editScrollProgressivize = true;
+        } else {
+            targetDoc.editScrollProgressivize = false;
+        }
+    }
+
+    //Progressivize Zoom
+    @action
+    progressivizeScroll = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        const activeItem: Doc = this.activeItem;
+        activeItem.scrollProgressivize = !activeItem.scrollProgressivize;
+        const targetDoc: Doc = this.targetDoc;
+        targetDoc.scrollProgressivize = !targetDoc.scrollProgressivize;
+        // CollectionFreeFormDocumentView.setupScroll(targetDoc, NumCast(targetDoc._currentFrame));
+        if (targetDoc.editScrollProgressivize) {
+            targetDoc.editScrollProgressivize = false;
+            targetDoc._currentFrame = 0;
+            targetDoc.lastFrame = 0;
+        }
+    }
+
+    //Progressivize Zoom
+    @action
+    progressivizeZoom = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        const activeItem: Doc = this.activeItem;
+        activeItem.zoomProgressivize = !activeItem.zoomProgressivize;
+        const targetDoc: Doc = this.targetDoc;
+        targetDoc.zoomProgressivize = !targetDoc.zoomProgressivize;
+        CollectionFreeFormDocumentView.setupZoom(activeItem, targetDoc);
+        if (activeItem.editZoomProgressivize) {
+            activeItem.editZoomProgressivize = false;
+            targetDoc._currentFrame = 0;
+            targetDoc.lastFrame = 0;
+        }
+    }
+
+    //Progressivize Child Docs
+    @action
+    editProgressivize = (e: React.MouseEvent) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        targetDoc._currentFrame = targetDoc.lastFrame;
+        if (!targetDoc.editProgressivize) {
+            if (!activeItem.presProgressivize) { activeItem.presProgressivize = true; targetDoc.presProgressivize = true; }
+            targetDoc.editProgressivize = true;
+        } else {
+            targetDoc.editProgressivize = false;
+        }
+    }
+
+    @action
+    progressivizeChild = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+        if (!activeItem.presProgressivize) {
+            targetDoc.keyFrameEditing = false;
+            activeItem.presProgressivize = true;
+            targetDoc.presProgressivize = true;
+            targetDoc._currentFrame = 0;
+            docs.forEach((doc, i) => CollectionFreeFormDocumentView.setupKeyframes([doc], i, true));
+            targetDoc.lastFrame = targetDoc.lastFrame ? NumCast(targetDoc.lastFrame) : docs.length - 1;
+        } else {
+            // targetDoc.editProgressivize = false;
+            activeItem.presProgressivize = false;
+            targetDoc.presProgressivize = false;
+            targetDoc._currentFrame = 0;
+            targetDoc.keyFrameEditing = true;
+        }
+    }
+
+    @action
+    checkMovementLists = (doc: Doc, xlist: any, ylist: any) => {
+        const x: List<number> = xlist;
+        const y: List<number> = ylist;
+        const tags: JSX.Element[] = [];
+        let pathPoints = ""; //List of all of the pathpoints that need to be added
+        for (let i = 0; i < x.length - 1; i++) {
+            if (y[i] || x[i]) {
+                if (i === 0) pathPoints = (x[i] - 11) + "," + (y[i] + 33);
+                else pathPoints = pathPoints + " " + (x[i] - 11) + "," + (y[i] + 33);
+                tags.push(<div className="progressivizeMove-frame" style={{ position: 'absolute', top: y[i], left: x[i] }}>{i}</div>);
+            }
+        }
+        tags.push(<svg style={{ overflow: 'visible', position: 'absolute' }}><polyline
+            points={pathPoints}
+            style={{
+                position: 'absolute',
+                opacity: 1,
+                stroke: "#000000",
+                strokeWidth: 2,
+                strokeDasharray: '10 5',
+            }}
+            fill="none"
+        /></svg>);
+        return tags;
+    }
+
+    @observable
+    toggleDisplayMovement = (doc: Doc) => {
+        if (doc.displayMovement) doc.displayMovement = false;
+        else doc.displayMovement = true;
+    }
+
+    @action
+    checkList = (doc: Doc, list: any): number => {
+        const x: List<number> = list;
+        if (x && x.length >= NumCast(doc._currentFrame) + 1) {
+            return x[NumCast(doc._currentFrame)];
+        } else if (x) {
+            x.length = NumCast(doc._currentFrame) + 1;
+            x[NumCast(doc._currentFrame)] = x[NumCast(doc._currentFrame) - 1];
+            return x[NumCast(doc._currentFrame)];
+        } else return 100;
+    }
+
+    @computed get progressivizeChildDocs() {
+        const targetDoc: Doc = this.targetDoc;
+        const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
+        const tags: JSX.Element[] = [];
+        docs.forEach((doc, index) => {
+            if (doc["x-indexed"] && doc["y-indexed"]) {
+                tags.push(<div style={{ position: 'absolute', display: doc.displayMovement ? "block" : "none" }}>{this.checkMovementLists(doc, doc["x-indexed"], doc["y-indexed"])}</div>);
+            }
+            tags.push(
+                <div className="progressivizeButton" key={index} onPointerLeave={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0; }} onPointerOver={() => { if (NumCast(targetDoc._currentFrame) < NumCast(doc.appearFrame)) doc.opacity = 0.5; }} onClick={e => { this.toggleDisplayMovement(doc); e.stopPropagation(); }} style={{ backgroundColor: doc.displayMovement ? Colors.LIGHT_BLUE : "#c8c8c8", top: NumCast(doc.y), left: NumCast(doc.x) }}>
+                    <div className="progressivizeButton-prev"><FontAwesomeIcon icon={"caret-left"} size={"lg"} onClick={e => { e.stopPropagation(); this.prevAppearFrame(doc, index); }} /></div>
+                    <div className="progressivizeButton-frame">{doc.appearFrame}</div>
+                    <div className="progressivizeButton-next"><FontAwesomeIcon icon={"caret-right"} size={"lg"} onClick={e => { e.stopPropagation(); this.nextAppearFrame(doc, index); }} /></div>
+                </div>);
+        });
+        return tags;
+    }
+
+    @action
+    nextAppearFrame = (doc: Doc, i: number): void => {
+        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+        // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+        const appearFrame = Cast(doc.appearFrame, "number", null);
+        if (appearFrame === undefined) {
+            doc.appearFrame = 0;
+        }
+        doc.appearFrame = appearFrame + 1;
+        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
+    }
+
+    @action
+    prevAppearFrame = (doc: Doc, i: number): void => {
+        // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
+        // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
+        const appearFrame = Cast(doc.appearFrame, "number", null);
+        if (appearFrame === undefined) {
+            doc.appearFrame = 0;
+        }
+        doc.appearFrame = Math.max(0, appearFrame - 1);
+        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
+    }
+
+    @action
+    updateOpacityList = (list: any, frame: number) => {
+        const x: List<number> = list;
+        if (x && x.length >= frame) {
+            for (let i = 0; i < x.length; i++) {
+                if (i < frame) {
+                    x[i] = 0;
+                } else if (i >= frame) {
+                    x[i] = 1;
+                }
+            }
+            list = x;
+        } else {
+            x.length = frame + 1;
+            for (let i = 0; i < x.length; i++) {
+                if (i < frame) {
+                    x[i] = 0;
+                } else if (i >= frame) {
+                    x[i] = 1;
+                }
+            }
+            list = x;
+        }
+    }
+
+    @computed get moreInfoDropdown() {
+        return (<div></div>);
+    }
+
+    @computed
+    get toolbarWidth(): number {
+        const width = this.props.PanelWidth();
+        return width;
+    }
+
+    @action
+    toggleProperties = () => {
+        if (CurrentUserUtils.propertiesWidth > 0) {
+            CurrentUserUtils.propertiesWidth = 0;
+        } else {
+            CurrentUserUtils.propertiesWidth = 250;
+        }
+    }
+
+    @computed get toolbar() {
+        const propIcon = CurrentUserUtils.propertiesWidth > 0 ? "angle-double-right" : "angle-double-left";
+        const propTitle = CurrentUserUtils.propertiesWidth > 0 ? "Close Presentation Panel" : "Open Presentation Panel";
+        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
+        const isMini: boolean = this.toolbarWidth <= 100;
+        const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
+        const activeColor = Colors.LIGHT_BLUE;
+        const inactiveColor = Colors.WHITE;
+        return (mode === CollectionViewType.Carousel3D) ? (null) : (
+            <div id="toolbarContainer" className={'presBox-toolbar'}>
+                {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
+                    <FontAwesomeIcon icon={"plus"} />
+                    <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+                </div></Tooltip> */}
+                <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}>
+                    <div style={{ opacity: this.childDocs.length > 1 && this.layoutDoc.presCollection ? 1 : 0.3, color: this._pathBoolean ? Colors.MEDIUM_BLUE : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 && this.layoutDoc.presCollection ? this.viewPaths : undefined}>
+                        <FontAwesomeIcon icon={"exchange-alt"} />
+                    </div>
+                </Tooltip>
+                {isMini ? (null) :
+                    <>
+                        <div className="toolbar-divider" />
+                        {/* <Tooltip title={<><div className="dash-tooltip">{this._expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
+                            <div className={"toolbar-button"}
+                                style={{ color: this._expandBoolean ? Colors.MEDIUM_BLUE : 'white' }}
+                                onClick={this.toggleExpandMode}>
+                                <FontAwesomeIcon icon={"eye"} />
+                            </div>
+                        </Tooltip>
+                        <div className="toolbar-divider" /> */}
+                        <Tooltip title={<><div className="dash-tooltip">{presKeyEvents ? "Keys are active" : "Keys are not active - click anywhere on the presentation trail to activate keys"}</div></>}>
+                            <div className="toolbar-button" style={{ cursor: presKeyEvents ? 'default' : 'pointer', position: 'absolute', right: 30, fontSize: 16 }}>
+                                <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"keyboard"} style={{ color: presKeyEvents ? activeColor : inactiveColor }} />
+                            </div>
+                        </Tooltip>
+                        <Tooltip title={<><div className="dash-tooltip">{propTitle}</div></>}>
+                            <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
+                                <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? activeColor : inactiveColor }} />
+                            </div>
+                        </Tooltip>
+                    </>
+                }
+            </div>
+        );
+    }
+
+    /**
+     * Top panel containes:
+     * viewPicker: The option to choose between List and Slides view for the presentaiton trail
+     * presentPanel: The button to start the presentation / open minimized view of the presentation
+     */
+    @computed get topPanel() {
+        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
+        const isMini: boolean = this.toolbarWidth <= 100;
+        return (
+            <div className="presBox-buttons" style={{ display: !this.rootDoc._chromeHidden ? "none" : undefined }}>
+                {isMini ? (null) : <select className="presBox-viewPicker"
+                    style={{ display: this.layoutDoc.presStatus === "edit" ? "block" : "none" }}
+                    onPointerDown={e => e.stopPropagation()}
+                    onChange={this.viewChanged}
+                    value={mode}>
+                    <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option>
+                    <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel3D}>3D Carousel</option>
+                </select>}
+                <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}>
+                    <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}>
+                        <div className="presBox-button-left"
+                            onClick={undoBatch(() => {
+                                if (this.childDocs.length) {
+                                    this.layoutDoc.presStatus = "manual";
+                                    this.gotoDocument(this.itemIndex, this.activeItem);
+                                }
+                            })}>
+                            <FontAwesomeIcon icon={"play-circle"} />
+                            <div style={{ display: this.props.PanelWidth() > 200 ? "inline-flex" : "none" }}>&nbsp; Present</div>
+                        </div>
+                        {(mode === CollectionViewType.Carousel3D || isMini) ? (null) : <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`}
+                            onClick={(action(() => {
+                                if (this.childDocs.length) this.presentTools = !this.presentTools;
+                            }))}>
+                            <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
+                            {this.presentDropdown}
+                        </div>}
+                    </span>
+                    {this.playButtons}
+                </div>
+            </div>
+        );
+    }
+
+    @action
+    getList = (list: any): List<number> => {
+        const x: List<number> = list;
+        return x;
+    }
+
+    @action
+    updateList = (list: any): List<number> => {
+        const targetDoc: Doc = this.targetDoc;
+        const x: List<number> = list;
+        x.length + 1;
+        x[x.length - 1] = NumCast(targetDoc._scrollY);
+        return x;
+    }
+
+    @action
+    newFrame = () => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const type: string = StrCast(targetDoc.type);
+        if (!activeItem.frameList) activeItem.frameList = new List<number>();
+        switch (type) {
+            case (DocumentType.PDF || DocumentType.RTF || DocumentType.WEB):
+                this.updateList(activeItem.frameList);
+                break;
+            case DocumentType.COL:
+                break;
+            default:
+                break;
+        }
+    }
+
+    @computed get frameListHeader() {
+        return (<div className="frameList-header">
+            &nbsp; Frames {this.panable ? <i>Panable</i> : this.scrollable ? <i>Scrollable</i> : (null)}
+            <div className={"frameList-headerButtons"}>
+                <Tooltip title={<><div className="dash-tooltip">{"Add frame by example"}</div></>}><div className={"headerButton"} onClick={e => { e.stopPropagation(); this.newFrame(); }}>
+                    <FontAwesomeIcon icon={"plus"} onPointerDown={e => e.stopPropagation()} />
+                </div></Tooltip>
+                <Tooltip title={<><div className="dash-tooltip">{"Edit in collection"}</div></>}><div className={"headerButton"} onClick={e => { e.stopPropagation(); console.log('New frame'); }}>
+                    <FontAwesomeIcon icon={"edit"} onPointerDown={e => e.stopPropagation()} />
+                </div></Tooltip>
+            </div>
+        </div>);
+    }
+
+    @computed get frameList() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const frameList: List<number> = this.getList(activeItem.frameList);
+        if (frameList) {
+            const frameItems = frameList.map((value) =>
+                <div className="framList-item">
+
+                </div>
+            );
+            return (
+
+                <div className="frameList-container">
+                    {frameItems}
+                </div>
+            );
+        } else return (null);
+
+    }
+
+    @computed get playButtonFrames() {
+        const targetDoc: Doc = this.targetDoc;
+        return (
+            <>
+                {this.targetDoc ? <div className="presPanel-button-frame" style={{ display: targetDoc.lastFrame !== undefined && targetDoc.lastFrame >= 0 ? "inline-flex" : "none" }}>
+                    <div>{targetDoc._currentFrame}</div>
+                    <div className="presPanel-divider" style={{ border: 'solid 0.5px white', height: '60%' }}></div>
+                    <div>{targetDoc.lastFrame}</div>
+                </div> : null}
+            </>
+        );
+    }
+
+    @computed get playButtons() {
+        const presEnd: boolean = !this.layoutDoc.presLoop && (this.itemIndex === this.childDocs.length - 1);
+        const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0);
+        // Case 1: There are still other frames and should go through all frames before going to next slide
+        return (<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}>
+            <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
+            <div className="presPanel-divider"></div>
+            <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
+            <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? "pause" : "play"} /></div></Tooltip>
+            <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
+            <div className="presPanel-divider"></div>
+            <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
+            <div
+                className="presPanel-button-text"
+                onClick={() => this.gotoDocument(0, this.activeItem)}
+                style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}>
+                Slide {this.itemIndex + 1} / {this.childDocs.length}
+                {this.playButtonFrames}
+            </div>
+            <div className="presPanel-divider"></div>
+            {this.props.PanelWidth() > 250 ? <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }))}>EXIT</div>
+                : <div className="presPanel-button" onClick={undoBatch(action(() => this.layoutDoc.presStatus = "edit"))}>
+                    <FontAwesomeIcon icon={"times"} />
+                </div>}
+        </div>);
+    }
+
+    @action
+    startOrPause = () => {
+        if (this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startAutoPres(this.itemIndex);
+        else this.pauseAutoPres();
+    }
+
+    render() {
+        // calling this method for keyEvents
+        this.isPres;
+        // needed to ensure that the childDocs are loaded for looking up fields
+        this.childDocs.slice();
+        const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
+        const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
+        const presEnd: boolean = !this.layoutDoc.presLoop && (this.itemIndex === this.childDocs.length - 1);
+        const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0);
+        return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ?
+            <div className="miniPres">
+                <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + Colors.MEDIUM_BLUE : undefined }}>
+                    <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
+                    <div className="presPanel-divider"></div>
+                    <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
+                    <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
+                    <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
+                    <div className="presPanel-divider"></div>
+                    <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
+                    <div className="presPanel-button-text">
+                        Slide {this.itemIndex + 1} / {this.childDocs.length}
+                        {this.playButtonFrames}
+                    </div>
+                    <div className="presPanel-divider"></div>
+                    <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.updateMinimize(); this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); }))}>EXIT</div>
+                </div>
+            </div>
+            :
+            <div className="presBox-cont" style={{ minWidth: CurrentUserUtils.OverlayDocs.includes(this.layoutDoc) ? 240 : undefined }} >
+                {this.topPanel}
+                {this.toolbar}
+                {this.newDocumentToolbarDropdown}
+                <div className="presBox-listCont">
+                    {mode !== CollectionViewType.Invalid ?
+                        <CollectionView {...this.props}
+                            ContainingCollectionDoc={this.props.Document}
+                            PanelWidth={this.props.PanelWidth}
+                            PanelHeight={this.panelHeight}
+                            childIgnoreNativeSize={true}
+                            moveDocument={returnFalse}
+                            childFitWidth={returnTrue}
+                            childOpacity={returnOne}
+                            childLayoutTemplate={this.childLayoutTemplate}
+                            filterAddDocument={this.addDocumentFilter}
+                            removeDocument={returnFalse}
+                            dontRegisterView={true}
+                            focus={this.selectElement}
+                            ScreenToLocalTransform={this.getTransform}
+                        />
+                        : (null)
+                    }
+                </div>
+            </div>;
+    }
+}
+Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, data: Doc) {
+    if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
+    if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 35 : 31;
+    if (field === 'presStatus') return container.presStatus;
+    if (field === '_itemIndex') return container._itemIndex;
+    if (field === 'presBox') return container;
+    return undefined;
+});
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss
new file mode 100644
index 000000000..1ad4b820e
--- /dev/null
+++ b/src/client/views/nodes/trails/PresElementBox.scss
@@ -0,0 +1,235 @@
+$light-blue: #AEDDF8;
+$dark-blue: #5B9FDD;
+$light-background: #ececec;
+$slide-background: #d5dce2;
+$slide-active: #5B9FDD;
+
+.presItem-container {
+    cursor: grab;
+    display: grid;
+    grid-template-columns: 20px auto;
+    font-family: Roboto;
+    letter-spacing: normal;
+    position: relative;
+    pointer-events: all;
+    width: 100%;
+    height: 100%;
+    font-weight: 400;
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    align-items: center;
+
+    .presItem-number {
+        margin-top: 3.5px;
+        font-size: 12px;
+        font-weight: 700;
+        text-align: center;
+        justify-self: center;
+        align-self: flex-start;
+        position: relative;
+        display: inline-block;
+        overflow: hidden;
+    }
+
+}
+
+.presItem-slide {
+    position: relative;
+    background-color: #d5dce2;
+    border-radius: 5px;
+    height: calc(100% - 7px);
+    width: calc(100% - 15px);
+    display: grid;
+    grid-template-rows: 16px 10px auto;
+    grid-template-columns: max-content max-content max-content max-content auto;
+
+    .presItem-name {
+        min-width: 20px;
+        z-index: 300;
+        top: 2px;
+        align-self: center;
+        font-size: 11px;
+        font-family: Roboto;
+        font-weight: 500;
+        position: relative;
+        padding-left: 10px;
+        padding-right: 10px;
+        letter-spacing: normal;
+        width: max-content;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        white-space: pre;
+    }
+
+    .presItem-docName {
+        min-width: 20px;
+        z-index: 300;
+        align-self: center;
+        font-size: 9px;
+        font-family: Roboto;
+        font-weight: 300;
+        position: relative;
+        padding-left: 10px;
+        padding-right: 10px;
+        letter-spacing: normal;
+        width: max-content;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        white-space: pre;
+        grid-row: 2;
+        grid-column: 1/6;
+    }
+
+    .presItem-time {
+        align-self: center;
+        position: relative;
+        padding-right: 10px;
+        top: 1px;
+        font-size: 10;
+        font-weight: 300;
+        font-family: Roboto;
+        z-index: 300;
+        letter-spacing: normal;
+    }
+
+    .presItem-embedded {
+        overflow: hidden;
+        grid-row: 3;
+        grid-column: 1/8;
+        position: relative;
+        display: flex;
+        width: auto;
+        justify-content: center;
+        margin: auto;
+        margin-bottom: 2px;
+        border-bottom-left-radius: 5px;
+        border-bottom-right-radius: 5px;
+    }
+
+    .presItem-embeddedMask {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+        border-radius: 3px;
+        top: 0;
+        left: 0;
+        z-index: 1;
+        overflow: hidden;
+    }
+
+
+    .presItem-slideButtons {
+        display: flex;
+        grid-column: 7;
+        grid-row: 1/3;
+        width: max-content;
+        justify-self: right;
+        justify-content: flex-end;
+
+        .slideButton {
+            cursor: pointer;
+            position: relative;
+            border-radius: 100px;
+            z-index: 300;
+            width: 18px;
+            height: 18px;
+            display: flex;
+            font-size: 12px;
+            justify-self: center;
+            align-self: center;
+            background-color: rgba(0, 0, 0, 0.5);
+            color: white;
+            justify-content: center;
+            align-items: center;
+            transition: 0.2s;
+            margin-right: 3px;
+        }
+
+        .slideButton:hover {
+            background-color: rgba(0, 0, 0, 1);
+            transform: scale(1.2);
+        }
+    }
+}
+
+// .presItem-slide:hover {
+//     .presItem-slideButtons {
+//         display: flex;
+//         grid-column: 7;
+//         grid-row: 1/3;
+//         width: max-content;
+//         justify-self: right;
+//         justify-content: flex-end;
+
+//         .slideButton {
+//             cursor: pointer;
+//             position: relative;
+//             border-radius: 100px;
+//             z-index: 300;
+//             width: 18px;
+//             height: 18px;
+//             display: flex;
+//             font-size: 12px;
+//             justify-self: center;
+//             align-self: center;
+//             background-color: rgba(0, 0, 0, 0.5);
+//             color: white;
+//             justify-content: center;
+//             align-items: center;
+//             transition: 0.2s;
+//             margin-right: 3px;
+//         }
+
+//         .slideButton:hover {
+//             background-color: rgba(0, 0, 0, 1);
+//             transform: scale(1.2);
+//         }
+//     }
+// }
+
+.presItem-slide.active {
+    box-shadow: 0 0 0px 1.5px $dark-blue;
+}
+
+.presItem-multiDrag {
+    font-family: Roboto;
+    font-weight: 600;
+    color: white;
+    text-align: center;
+    justify-content: center;
+    align-content: center;
+    width: 100px;
+    height: 30px;
+    position: absolute;
+    background-color: $dark-blue;
+    z-index: 4000;
+    border-radius: 10px;
+    box-shadow: black 0.4vw 0.4vw 0.8vw;
+    line-height: 30px;
+}
+
+.presItem-miniSlide {
+    font-weight: 700;
+    font-size: 12;
+    grid-column: 1/8;
+    align-self: center;
+    justify-self: center;
+    background-color: #d5dce2;
+    width: 26px;
+    text-align: center;
+    height: 26px;
+    line-height: 28px;
+    border-radius: 100%;
+}
+
+.presItem-miniSlide.active {
+    box-shadow: 0 0 0px 1.5px $dark-blue;
+}
+
+// .presItem-slide:hover {
+//     background: $slide-hover;
+// }
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
new file mode 100644
index 000000000..5e713c3cf
--- /dev/null
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -0,0 +1,388 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
+import { observer } from "mobx-react";
+import { DataSym, Doc, Opt } from "../../../../fields/Doc";
+import { documentSchema } from '../../../../fields/documentSchemas';
+import { Id } from "../../../../fields/FieldSymbols";
+import { createSchema, makeInterface } from '../../../../fields/Schema';
+import { Cast, NumCast, StrCast } from "../../../../fields/Types";
+import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, emptyPath, returnEmptyDoclist } from "../../../../Utils";
+import { DocumentType } from "../../../documents/DocumentTypes";
+import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
+import { DocumentManager } from "../../../util/DocumentManager";
+import { DragManager } from "../../../util/DragManager";
+import { Transform } from "../../../util/Transform";
+import { undoBatch } from "../../../util/UndoManager";
+import { ViewBoxBaseComponent } from '../../DocComponent';
+import { EditableView } from "../../EditableView";
+import { DocumentView, DocumentViewProps } from "../../nodes/DocumentView";
+import { FieldView, FieldViewProps } from '../../nodes/FieldView';
+import { PresBox } from "./PresBox";
+import { Colors } from "../../global/globalEnums";
+import { StyleProp } from "../../StyleProvider";
+import "./PresElementBox.scss";
+import React = require("react");
+import { DocUtils } from "../../../documents/Documents";
+import { PresMovement } from "./PresEnums";
+
+export const presSchema = createSchema({
+    presentationTargetDoc: Doc,
+    presBox: Doc,
+    presZoomButton: "boolean",
+    presNavButton: "boolean",
+    presHideTillShownButton: "boolean",
+    presFadeButton: "boolean",
+    presHideAfterButton: "boolean",
+    presGroupButton: "boolean",
+    presExpandInlineButton: "boolean"
+});
+
+type PresDocument = makeInterface<[typeof presSchema, typeof documentSchema]>;
+const PresDocument = makeInterface(presSchema, documentSchema);
+/**
+ * This class models the view a document added to presentation will have in the presentation.
+ * It involves some functionality for its buttons and options.
+ */
+@observer
+export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDocument>(PresDocument) {
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
+    _heightDisposer: IReactionDisposer | undefined;
+
+    @observable _dragging = false;
+    // these fields are conditionally computed fields on the layout document that take this document as a parameter
+    @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
+    @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
+    @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
+    @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
+    @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
+    @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
+
+    componentDidMount() {
+        this.layoutDoc.hideLinkButton = true;
+        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
+            params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
+    }
+    componentWillUnmount() {
+        this._heightDisposer?.();
+    }
+
+    /**
+     * Returns a local transformed coordinate array for given coordinates.
+     */
+    ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
+
+    @action
+    presExpandDocumentClick = () => {
+        this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
+    }
+
+    embedHeight = (): number => 97;
+    // embedWidth = () => this.props.PanelWidth();
+    // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
+    embedWidth = (): number => this.props.PanelWidth() - 35;
+    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
+        if (property === StyleProp.Opacity) return 1;
+        return this.props.styleProvider?.(doc, props, property);
+    }
+    /**
+     * The function that is responsible for rendering a preview or not for this
+     * presentation element.
+     */
+    @computed get renderEmbeddedInline() {
+        return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
+            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
+                <DocumentView
+                    Document={this.targetDoc}
+                    DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
+                    styleProvider={this.styleProvider}
+                    layerProvider={this.props.layerProvider}
+                    docViewPath={returnEmptyDoclist}
+                    rootSelected={returnTrue}
+                    addDocument={returnFalse}
+                    removeDocument={returnFalse}
+                    isContentActive={this.props.isContentActive}
+                    addDocTab={returnFalse}
+                    pinToPres={returnFalse}
+                    PanelWidth={this.embedWidth}
+                    PanelHeight={this.embedHeight}
+                    ScreenToLocalTransform={Transform.Identity}
+                    moveDocument={this.props.moveDocument!}
+                    renderDepth={this.props.renderDepth + 1}
+                    focus={DocUtils.DefaultFocus}
+                    whenChildContentsActiveChanged={returnFalse}
+                    bringToFront={returnFalse}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
+                    hideLinkButton={true}
+                />
+                <div className="presItem-embeddedMask" />
+            </div>;
+    }
+
+    @computed get duration() {
+        let durationInS: number;
+        if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
+        else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
+        else durationInS = 2;
+        return "D: " + durationInS + "s";
+    }
+
+    @computed get transition() {
+        let transitionInS: number;
+        if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
+        else transitionInS = 0.5;
+        return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
+    }
+
+    private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _titleRef: React.RefObject<EditableView> = React.createRef();
+
+
+    @action
+    headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+        const element = e.target as any;
+        e.stopPropagation();
+        e.preventDefault();
+        if (element && !(e.ctrlKey || e.metaKey)) {
+            if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
+                PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
+            } else {
+                setupMoveUpEvents(this, e, ((e: PointerEvent) => {
+                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
+                    return this.startDrag(e);
+                }), emptyFunction, emptyFunction);
+            }
+        }
+    }
+
+    headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    startDrag = (e: PointerEvent) => {
+        const miniView: boolean = this.toolbarWidth <= 100;
+        const activeItem = this.rootDoc;
+        const dragArray = PresBox.Instance._dragArray;
+        const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
+        const dragItem: HTMLElement[] = [];
+        if (dragArray.length === 1) {
+            const doc = dragArray[0];
+            doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
+            dragItem.push(doc);
+        } else if (dragArray.length >= 1) {
+            const doc = document.createElement('div');
+            doc.className = "presItem-multiDrag";
+            doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
+            doc.style.position = 'absolute';
+            doc.style.top = (e.clientY) + 'px';
+            doc.style.left = (e.clientX - 50) + 'px';
+            dragItem.push(doc);
+        }
+
+        // const dropEvent = () => runInAction(() => this._dragging = false);
+        if (activeItem) {
+            DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
+            // runInAction(() => this._dragging = true);
+            return true;
+        }
+        return false;
+    }
+
+    onPointerOver = (e: any) => {
+        document.removeEventListener("pointermove", this.onPointerMove);
+        document.addEventListener("pointermove", this.onPointerMove);
+    }
+
+    onPointerMove = (e: PointerEvent) => {
+        const slide = this._itemRef.current!;
+        let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
+        for (const doc of DragManager.docsBeingDragged) {
+            if (!doc.presentationTargetDoc) dragIsPresItem = false;
+        }
+        if (slide && dragIsPresItem) {
+            const rect = slide.getBoundingClientRect();
+            const y = e.clientY - rect.top;  //y position within the element.
+            const height = slide.clientHeight;
+            const halfLine = height / 2;
+            if (y <= halfLine) {
+                slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                slide.style.borderBottom = "0px";
+            } else if (y > halfLine) {
+                slide.style.borderTop = "0px";
+                slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
+            }
+        }
+        document.removeEventListener("pointermove", this.onPointerMove);
+    }
+
+    onPointerLeave = (e: any) => {
+        this._itemRef.current!.style.borderTop = "0px";
+        this._itemRef.current!.style.borderBottom = "0px";
+        document.removeEventListener("pointermove", this.onPointerMove);
+    }
+
+    @action
+    toggleProperties = () => {
+        if (CurrentUserUtils.propertiesWidth < 5) {
+            action(() => (CurrentUserUtils.propertiesWidth = 250));
+        }
+    }
+
+    @undoBatch
+    removeItem = action((e: React.MouseEvent) => {
+        this.props.removeDocument?.(this.rootDoc);
+        if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
+            PresBox.Instance._selectedArray.delete(this.rootDoc);
+        }
+        e.stopPropagation();
+    });
+
+    @undoBatch
+    @action
+    onSetValue = (value: string) => {
+        this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
+        return true;
+    }
+
+    /**
+     * Method called for updating the view of the currently selected document
+     * 
+     * @param targetDoc 
+     * @param activeItem 
+     */
+    @undoBatch
+    @action
+    updateView = (targetDoc: Doc, activeItem: Doc) => {
+        if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
+            const scroll = targetDoc._scrollTop;
+            activeItem.presPinViewScroll = scroll;
+        } else if (targetDoc.type === DocumentType.VID) {
+            activeItem.presPinTimecode = targetDoc._currentTimecode;
+        } else if (targetDoc.type === DocumentType.COMPARISON) {
+            const clipWidth = targetDoc._clipWidth;
+            activeItem.presPinClipWidth = clipWidth;
+        } else {
+            const x = targetDoc._panX;
+            const y = targetDoc._panY;
+            const scale = targetDoc._viewScale;
+            activeItem.presPinViewX = x;
+            activeItem.presPinViewY = y;
+            activeItem.presPinViewScale = scale;
+        }
+    }
+
+    @computed
+    get toolbarWidth(): number {
+        const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
+        let width: number = NumCast(this.presBox._width);
+        if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
+        if (width === 0) width = 300;
+        return width;
+    }
+
+    @computed get mainItem() {
+        const isSelected: boolean = PresBox.Instance._selectedArray.has(this.rootDoc);
+        const toolbarWidth: number = this.toolbarWidth;
+        const showMore: boolean = this.toolbarWidth >= 300;
+        const miniView: boolean = this.toolbarWidth <= 110;
+        const presBox: Doc = this.presBox; //presBox
+        const presBoxColor: string = StrCast(presBox._backgroundColor);
+        const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false;
+        const targetDoc: Doc = this.targetDoc;
+        const activeItem: Doc = this.rootDoc;
+        return (
+            <div className={`presItem-container`}
+                key={this.props.Document[Id] + this.indexInPres}
+                ref={this._itemRef}
+                style={{
+                    backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? Colors.LIGHT_BLUE : "transparent",
+                    opacity: this._dragging ? 0.3 : 1
+                }}
+                onClick={e => {
+                    e.stopPropagation();
+                    e.preventDefault();
+                    PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
+                }}
+                onDoubleClick={action(e => {
+                    this.toggleProperties();
+                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
+                })}
+                onPointerOver={this.onPointerOver}
+                onPointerLeave={this.onPointerLeave}
+                onPointerDown={this.headerDown}
+                onPointerUp={this.headerUp}
+            >
+                {miniView ?
+                    // when width is LESS than 110 px 
+                    <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
+                        {`${this.indexInPres + 1}.`}
+                    </div>
+                    :
+                    // when width is MORE than 110 px 
+                    <div className="presItem-number">
+                        {`${this.indexInPres + 1}.`}
+                    </div>}
+                {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
+                    style={{
+                        backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
+                        boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
+                    }}>
+                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
+                        <EditableView
+                            ref={this._titleRef}
+                            editing={!isSelected ? false : undefined}
+                            contents={activeItem.title}
+                            overflow={'ellipsis'}
+                            GetValue={() => StrCast(activeItem.title)}
+                            SetValue={this.onSetValue}
+                        />
+                    </div>
+                    <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
+                    <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
+                    <div className={"presItem-slideButtons"}>
+                        <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
+                            <div className="slideButton"
+                                onClick={() => this.updateView(targetDoc, activeItem)}
+                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
+                        </Tooltip>
+                        {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
+                            <div className="slideButton"
+                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
+                                style={{
+                                    zIndex: 1000 - this.indexInPres,
+                                    fontWeight: 700,
+                                    backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined,
+                                    height: activeItem.groupWithUp ? 53 : 18,
+                                    transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
+                                }}>
+                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
+                                    <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
+                                </div>
+                            </div>
+                        </Tooltip>}
+                        <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
+                            <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? "eye-slash" : "eye"} onPointerDown={e => e.stopPropagation()} />
+                        </div></Tooltip>
+                        <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
+                            className={"slideButton"}
+                            onClick={this.removeItem}>
+                            <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
+                        </div></Tooltip>
+                    </div>
+                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
+                    {this.renderEmbeddedInline}
+                </div>}
+            </div >);
+    }
+
+    render() {
+        return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/PresEnums.ts b/src/client/views/nodes/trails/PresEnums.ts
new file mode 100644
index 000000000..93ab323fb
--- /dev/null
+++ b/src/client/views/nodes/trails/PresEnums.ts
@@ -0,0 +1,28 @@
+export enum PresMovement {
+    Zoom = "zoom",
+    Pan = "pan",
+    Jump = "jump",
+    None = "none",
+}
+
+export enum PresEffect {
+    Zoom = "Zoom",
+    Lightspeed = "Lightspeed",
+    Fade = "Fade in",
+    Flip = "Flip",
+    Rotate = "Rotate",
+    Bounce = "Bounce",
+    Roll = "Roll",
+    None = "None",
+    Left = "left",
+    Right = "right",
+    Center = "center",
+    Top = "top",
+    Bottom = "bottom"
+}
+
+export enum PresStatus {
+    Autoplay = "auto",
+    Manual = "manual",
+    Edit = "edit"
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/trails/index.ts b/src/client/views/nodes/trails/index.ts
new file mode 100644
index 000000000..8f3f7b03a
--- /dev/null
+++ b/src/client/views/nodes/trails/index.ts
@@ -0,0 +1,3 @@
+export * from "./PresBox";
+export * from "./PresElementBox";
+export * from "./PresEnums";
\ No newline at end of file
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
deleted file mode 100644
index 1ad4b820e..000000000
--- a/src/client/views/presentationview/PresElementBox.scss
+++ /dev/null
@@ -1,235 +0,0 @@
-$light-blue: #AEDDF8;
-$dark-blue: #5B9FDD;
-$light-background: #ececec;
-$slide-background: #d5dce2;
-$slide-active: #5B9FDD;
-
-.presItem-container {
-    cursor: grab;
-    display: grid;
-    grid-template-columns: 20px auto;
-    font-family: Roboto;
-    letter-spacing: normal;
-    position: relative;
-    pointer-events: all;
-    width: 100%;
-    height: 100%;
-    font-weight: 400;
-    -webkit-touch-callout: none;
-    -webkit-user-select: none;
-    -khtml-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-    align-items: center;
-
-    .presItem-number {
-        margin-top: 3.5px;
-        font-size: 12px;
-        font-weight: 700;
-        text-align: center;
-        justify-self: center;
-        align-self: flex-start;
-        position: relative;
-        display: inline-block;
-        overflow: hidden;
-    }
-
-}
-
-.presItem-slide {
-    position: relative;
-    background-color: #d5dce2;
-    border-radius: 5px;
-    height: calc(100% - 7px);
-    width: calc(100% - 15px);
-    display: grid;
-    grid-template-rows: 16px 10px auto;
-    grid-template-columns: max-content max-content max-content max-content auto;
-
-    .presItem-name {
-        min-width: 20px;
-        z-index: 300;
-        top: 2px;
-        align-self: center;
-        font-size: 11px;
-        font-family: Roboto;
-        font-weight: 500;
-        position: relative;
-        padding-left: 10px;
-        padding-right: 10px;
-        letter-spacing: normal;
-        width: max-content;
-        text-overflow: ellipsis;
-        overflow: hidden;
-        white-space: pre;
-    }
-
-    .presItem-docName {
-        min-width: 20px;
-        z-index: 300;
-        align-self: center;
-        font-size: 9px;
-        font-family: Roboto;
-        font-weight: 300;
-        position: relative;
-        padding-left: 10px;
-        padding-right: 10px;
-        letter-spacing: normal;
-        width: max-content;
-        text-overflow: ellipsis;
-        overflow: hidden;
-        white-space: pre;
-        grid-row: 2;
-        grid-column: 1/6;
-    }
-
-    .presItem-time {
-        align-self: center;
-        position: relative;
-        padding-right: 10px;
-        top: 1px;
-        font-size: 10;
-        font-weight: 300;
-        font-family: Roboto;
-        z-index: 300;
-        letter-spacing: normal;
-    }
-
-    .presItem-embedded {
-        overflow: hidden;
-        grid-row: 3;
-        grid-column: 1/8;
-        position: relative;
-        display: flex;
-        width: auto;
-        justify-content: center;
-        margin: auto;
-        margin-bottom: 2px;
-        border-bottom-left-radius: 5px;
-        border-bottom-right-radius: 5px;
-    }
-
-    .presItem-embeddedMask {
-        width: 100%;
-        height: 100%;
-        position: absolute;
-        border-radius: 3px;
-        top: 0;
-        left: 0;
-        z-index: 1;
-        overflow: hidden;
-    }
-
-
-    .presItem-slideButtons {
-        display: flex;
-        grid-column: 7;
-        grid-row: 1/3;
-        width: max-content;
-        justify-self: right;
-        justify-content: flex-end;
-
-        .slideButton {
-            cursor: pointer;
-            position: relative;
-            border-radius: 100px;
-            z-index: 300;
-            width: 18px;
-            height: 18px;
-            display: flex;
-            font-size: 12px;
-            justify-self: center;
-            align-self: center;
-            background-color: rgba(0, 0, 0, 0.5);
-            color: white;
-            justify-content: center;
-            align-items: center;
-            transition: 0.2s;
-            margin-right: 3px;
-        }
-
-        .slideButton:hover {
-            background-color: rgba(0, 0, 0, 1);
-            transform: scale(1.2);
-        }
-    }
-}
-
-// .presItem-slide:hover {
-//     .presItem-slideButtons {
-//         display: flex;
-//         grid-column: 7;
-//         grid-row: 1/3;
-//         width: max-content;
-//         justify-self: right;
-//         justify-content: flex-end;
-
-//         .slideButton {
-//             cursor: pointer;
-//             position: relative;
-//             border-radius: 100px;
-//             z-index: 300;
-//             width: 18px;
-//             height: 18px;
-//             display: flex;
-//             font-size: 12px;
-//             justify-self: center;
-//             align-self: center;
-//             background-color: rgba(0, 0, 0, 0.5);
-//             color: white;
-//             justify-content: center;
-//             align-items: center;
-//             transition: 0.2s;
-//             margin-right: 3px;
-//         }
-
-//         .slideButton:hover {
-//             background-color: rgba(0, 0, 0, 1);
-//             transform: scale(1.2);
-//         }
-//     }
-// }
-
-.presItem-slide.active {
-    box-shadow: 0 0 0px 1.5px $dark-blue;
-}
-
-.presItem-multiDrag {
-    font-family: Roboto;
-    font-weight: 600;
-    color: white;
-    text-align: center;
-    justify-content: center;
-    align-content: center;
-    width: 100px;
-    height: 30px;
-    position: absolute;
-    background-color: $dark-blue;
-    z-index: 4000;
-    border-radius: 10px;
-    box-shadow: black 0.4vw 0.4vw 0.8vw;
-    line-height: 30px;
-}
-
-.presItem-miniSlide {
-    font-weight: 700;
-    font-size: 12;
-    grid-column: 1/8;
-    align-self: center;
-    justify-self: center;
-    background-color: #d5dce2;
-    width: 26px;
-    text-align: center;
-    height: 26px;
-    line-height: 28px;
-    border-radius: 100%;
-}
-
-.presItem-miniSlide.active {
-    box-shadow: 0 0 0px 1.5px $dark-blue;
-}
-
-// .presItem-slide:hover {
-//     background: $slide-hover;
-// }
\ No newline at end of file
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
deleted file mode 100644
index f15d51764..000000000
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ /dev/null
@@ -1,386 +0,0 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
-import { observer } from "mobx-react";
-import { DataSym, Doc, Opt } from "../../../fields/Doc";
-import { documentSchema } from '../../../fields/documentSchemas';
-import { Id } from "../../../fields/FieldSymbols";
-import { createSchema, makeInterface } from '../../../fields/Schema';
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, emptyPath, returnEmptyDoclist } from "../../../Utils";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DragManager } from "../../util/DragManager";
-import { Transform } from "../../util/Transform";
-import { undoBatch } from "../../util/UndoManager";
-import { ViewBoxBaseComponent } from '../DocComponent';
-import { EditableView } from "../EditableView";
-import { DocumentView, DocumentViewProps } from "../nodes/DocumentView";
-import { FieldView, FieldViewProps } from '../nodes/FieldView';
-import { PresBox, PresColor, PresMovement } from "../nodes/PresBox";
-import { StyleProp } from "../StyleProvider";
-import "./PresElementBox.scss";
-import React = require("react");
-import { DocUtils } from "../../documents/Documents";
-
-export const presSchema = createSchema({
-    presentationTargetDoc: Doc,
-    presBox: Doc,
-    presZoomButton: "boolean",
-    presNavButton: "boolean",
-    presHideTillShownButton: "boolean",
-    presFadeButton: "boolean",
-    presHideAfterButton: "boolean",
-    presGroupButton: "boolean",
-    presExpandInlineButton: "boolean"
-});
-
-type PresDocument = makeInterface<[typeof presSchema, typeof documentSchema]>;
-const PresDocument = makeInterface(presSchema, documentSchema);
-/**
- * This class models the view a document added to presentation will have in the presentation.
- * It involves some functionality for its buttons and options.
- */
-@observer
-export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDocument>(PresDocument) {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
-    _heightDisposer: IReactionDisposer | undefined;
-
-    @observable _dragging = false;
-    // these fields are conditionally computed fields on the layout document that take this document as a parameter
-    @computed get indexInPres() { return Number(this.lookupField("indexInPres")); }  // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements)
-    @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox.  We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up
-    @computed get presStatus() { return StrCast(this.lookupField("presStatus")); }
-    @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); }
-    @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); }
-    @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; }
-
-    componentDidMount() {
-        this.layoutDoc.hideLinkButton = true;
-        this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight],
-            params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true });
-    }
-    componentWillUnmount() {
-        this._heightDisposer?.();
-    }
-
-    /**
-     * Returns a local transformed coordinate array for given coordinates.
-     */
-    ScreenToLocalListTransform = (xCord: number, yCord: number) => [xCord, yCord];
-
-    @action
-    presExpandDocumentClick = () => {
-        this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton;
-    }
-
-    embedHeight = (): number => 97;
-    // embedWidth = () => this.props.PanelWidth();
-    // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight);
-    embedWidth = (): number => this.props.PanelWidth() - 35;
-    styleProvider = (doc: (Doc | undefined), props: Opt<DocumentViewProps>, property: string): any => {
-        if (property === StyleProp.Opacity) return 1;
-        return this.props.styleProvider?.(doc, props, property);
-    }
-    /**
-     * The function that is responsible for rendering a preview or not for this
-     * presentation element.
-     */
-    @computed get renderEmbeddedInline() {
-        return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
-            <div className="presItem-embedded" style={{ height: this.embedHeight(), width: this.embedWidth() }}>
-                <DocumentView
-                    Document={this.targetDoc}
-                    DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]}
-                    styleProvider={this.styleProvider}
-                    layerProvider={this.props.layerProvider}
-                    docViewPath={returnEmptyDoclist}
-                    rootSelected={returnTrue}
-                    addDocument={returnFalse}
-                    removeDocument={returnFalse}
-                    isContentActive={this.props.isContentActive}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
-                    PanelWidth={this.embedWidth}
-                    PanelHeight={this.embedHeight}
-                    ScreenToLocalTransform={Transform.Identity}
-                    moveDocument={this.props.moveDocument!}
-                    renderDepth={this.props.renderDepth + 1}
-                    focus={DocUtils.DefaultFocus}
-                    whenChildContentsActiveChanged={returnFalse}
-                    bringToFront={returnFalse}
-                    docFilters={this.props.docFilters}
-                    docRangeFilters={this.props.docRangeFilters}
-                    searchFilterDocs={this.props.searchFilterDocs}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined}
-                    hideLinkButton={true}
-                />
-                <div className="presItem-embeddedMask" />
-            </div>;
-    }
-
-    @computed get duration() {
-        let durationInS: number;
-        if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
-        else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
-        else durationInS = 2;
-        return "D: " + durationInS + "s";
-    }
-
-    @computed get transition() {
-        let transitionInS: number;
-        if (this.rootDoc.presTransition) transitionInS = NumCast(this.rootDoc.presTransition) / 1000;
-        else transitionInS = 0.5;
-        return this.rootDoc.presMovement === PresMovement.Jump || this.rootDoc.presMovement === PresMovement.None ? (null) : "M: " + transitionInS + "s";
-    }
-
-    private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
-    private _titleRef: React.RefObject<EditableView> = React.createRef();
-
-
-    @action
-    headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
-        const element = e.target as any;
-        e.stopPropagation();
-        e.preventDefault();
-        if (element && !(e.ctrlKey || e.metaKey)) {
-            if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-                PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
-            } else {
-                setupMoveUpEvents(this, e, ((e: PointerEvent) => {
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false);
-                    return this.startDrag(e);
-                }), emptyFunction, emptyFunction);
-            }
-        }
-    }
-
-    headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
-        e.stopPropagation();
-        e.preventDefault();
-    }
-
-    startDrag = (e: PointerEvent) => {
-        const miniView: boolean = this.toolbarWidth <= 100;
-        const activeItem = this.rootDoc;
-        const dragArray = PresBox.Instance._dragArray;
-        const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray());
-        const dragItem: HTMLElement[] = [];
-        if (dragArray.length === 1) {
-            const doc = dragArray[0];
-            doc.className = miniView ? "presItem-miniSlide" : "presItem-slide";
-            dragItem.push(doc);
-        } else if (dragArray.length >= 1) {
-            const doc = document.createElement('div');
-            doc.className = "presItem-multiDrag";
-            doc.innerText = "Move " + PresBox.Instance._selectedArray.size + " slides";
-            doc.style.position = 'absolute';
-            doc.style.top = (e.clientY) + 'px';
-            doc.style.left = (e.clientX - 50) + 'px';
-            dragItem.push(doc);
-        }
-
-        // const dropEvent = () => runInAction(() => this._dragging = false);
-        if (activeItem) {
-            DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY, undefined);
-            // runInAction(() => this._dragging = true);
-            return true;
-        }
-        return false;
-    }
-
-    onPointerOver = (e: any) => {
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.addEventListener("pointermove", this.onPointerMove);
-    }
-
-    onPointerMove = (e: PointerEvent) => {
-        const slide = this._itemRef.current!;
-        let dragIsPresItem: boolean = DragManager.docsBeingDragged.length > 0 ? true : false;
-        for (const doc of DragManager.docsBeingDragged) {
-            if (!doc.presentationTargetDoc) dragIsPresItem = false;
-        }
-        if (slide && dragIsPresItem) {
-            const rect = slide.getBoundingClientRect();
-            const y = e.clientY - rect.top;  //y position within the element.
-            const height = slide.clientHeight;
-            const halfLine = height / 2;
-            if (y <= halfLine) {
-                slide.style.borderTop = "solid 2px #5B9FDD";
-                slide.style.borderBottom = "0px";
-            } else if (y > halfLine) {
-                slide.style.borderTop = "0px";
-                slide.style.borderBottom = "solid 2px #5B9FDD";
-            }
-        }
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
-
-    onPointerLeave = (e: any) => {
-        this._itemRef.current!.style.borderTop = "0px";
-        this._itemRef.current!.style.borderBottom = "0px";
-        document.removeEventListener("pointermove", this.onPointerMove);
-    }
-
-    @action
-    toggleProperties = () => {
-        if (CurrentUserUtils.propertiesWidth < 5) {
-            action(() => (CurrentUserUtils.propertiesWidth = 250));
-        }
-    }
-
-    @undoBatch
-    removeItem = action((e: React.MouseEvent) => {
-        this.props.removeDocument?.(this.rootDoc);
-        if (PresBox.Instance._selectedArray.has(this.rootDoc)) {
-            PresBox.Instance._selectedArray.delete(this.rootDoc);
-        }
-        e.stopPropagation();
-    });
-
-    @undoBatch
-    @action
-    onSetValue = (value: string) => {
-        this.rootDoc.title = !value.trim().length ? "-untitled-" : value;
-        return true;
-    }
-
-    /**
-     * Method called for updating the view of the currently selected document
-     * 
-     * @param targetDoc 
-     * @param activeItem 
-     */
-    @undoBatch
-    @action
-    updateView = (targetDoc: Doc, activeItem: Doc) => {
-        if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) {
-            const scroll = targetDoc._scrollTop;
-            activeItem.presPinViewScroll = scroll;
-        } else if (targetDoc.type === DocumentType.VID) {
-            activeItem.presPinTimecode = targetDoc._currentTimecode;
-        } else if (targetDoc.type === DocumentType.COMPARISON) {
-            const clipWidth = targetDoc._clipWidth;
-            activeItem.presPinClipWidth = clipWidth;
-        } else {
-            const x = targetDoc._panX;
-            const y = targetDoc._panY;
-            const scale = targetDoc._viewScale;
-            activeItem.presPinViewX = x;
-            activeItem.presPinViewY = y;
-            activeItem.presPinViewScale = scale;
-        }
-    }
-
-    @computed
-    get toolbarWidth(): number {
-        const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox);
-        let width: number = NumCast(this.presBox._width);
-        if (presBoxDocView) width = presBoxDocView.props.PanelWidth();
-        if (width === 0) width = 300;
-        return width;
-    }
-
-    @computed get mainItem() {
-        const isSelected: boolean = PresBox.Instance._selectedArray.has(this.rootDoc);
-        const toolbarWidth: number = this.toolbarWidth;
-        const showMore: boolean = this.toolbarWidth >= 300;
-        const miniView: boolean = this.toolbarWidth <= 110;
-        const presBox: Doc = this.presBox; //presBox
-        const presBoxColor: string = StrCast(presBox._backgroundColor);
-        const presColorBool: boolean = presBoxColor ? (presBoxColor !== "white" && presBoxColor !== "transparent") : false;
-        const targetDoc: Doc = this.targetDoc;
-        const activeItem: Doc = this.rootDoc;
-        return (
-            <div className={`presItem-container`}
-                key={this.props.Document[Id] + this.indexInPres}
-                ref={this._itemRef}
-                style={{
-                    backgroundColor: presColorBool ? isSelected ? "rgba(250,250,250,0.3)" : "transparent" : isSelected ? "#AEDDF8" : "transparent",
-                    opacity: this._dragging ? 0.3 : 1
-                }}
-                onClick={e => {
-                    e.stopPropagation();
-                    e.preventDefault();
-                    PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
-                }}
-                onDoubleClick={action(e => {
-                    this.toggleProperties();
-                    PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true);
-                })}
-                onPointerOver={this.onPointerOver}
-                onPointerLeave={this.onPointerLeave}
-                onPointerDown={this.headerDown}
-                onPointerUp={this.headerUp}
-            >
-                {miniView ?
-                    // when width is LESS than 110 px 
-                    <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}>
-                        {`${this.indexInPres + 1}.`}
-                    </div>
-                    :
-                    // when width is MORE than 110 px 
-                    <div className="presItem-number">
-                        {`${this.indexInPres + 1}.`}
-                    </div>}
-                {miniView ? (null) : <div ref={miniView ? null : this._dragRef} className={`presItem-slide ${isSelected ? "active" : ""}`}
-                    style={{
-                        backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
-                        boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined
-                    }}>
-                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}>
-                        <EditableView
-                            ref={this._titleRef}
-                            editing={!isSelected ? false : undefined}
-                            contents={activeItem.title}
-                            overflow={'ellipsis'}
-                            GetValue={() => StrCast(activeItem.title)}
-                            SetValue={this.onSetValue}
-                        />
-                    </div>
-                    <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip>
-                    <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip>
-                    <div className={"presItem-slideButtons"}>
-                        <Tooltip title={<><div className="dash-tooltip">{"Update view"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => this.updateView(targetDoc, activeItem)}
-                                style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V</div>
-                        </Tooltip>
-                        {this.indexInPres === 0 ? (null) : <Tooltip title={<><div className="dash-tooltip">{activeItem.groupWithUp ? "Ungroup" : "Group with up"}</div></>}>
-                            <div className="slideButton"
-                                onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
-                                style={{
-                                    zIndex: 1000 - this.indexInPres,
-                                    fontWeight: 700,
-                                    backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : PresColor.DarkBlue : undefined,
-                                    height: activeItem.groupWithUp ? 53 : 18,
-                                    transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined
-                                }}>
-                                <div style={{ transform: activeItem.groupWithUp ? "rotate(180deg) translate(0, -17.5px)" : "rotate(0deg)" }}>
-                                    <FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} />
-                                </div>
-                            </div>
-                        </Tooltip>}
-                        <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}</div></>}><div className={"slideButton"} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}>
-                            <FontAwesomeIcon icon={this.rootDoc.presExpandInlineButton ? "eye-slash" : "eye"} onPointerDown={e => e.stopPropagation()} />
-                        </div></Tooltip>
-                        <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
-                            className={"slideButton"}
-                            onClick={this.removeItem}>
-                            <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
-                        </div></Tooltip>
-                    </div>
-                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
-                    {this.renderEmbeddedInline}
-                </div>}
-            </div >);
-    }
-
-    render() {
-        return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index 324b96dbd..e2d27d5a6 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -30,7 +30,7 @@
                 display: flex;
 
                 .topbar-dashboards {
-                    display: none;
+                    display: inline-flex;
                 }
 
                 .topbar-dashSelect {
@@ -46,12 +46,6 @@
                     }
                 }
             }
-
-            .topbar-lozenge-dashboard:hover {
-                .topbar-dashboards {
-                    display: inline-flex;
-                }
-            }
         }
 
         .topBar-icon {
@@ -85,7 +79,7 @@
             .topbar-lozenge {
                 height: 23;
                 font-size: 12;
-                color: black;
+                color: white;
                 font-family: 'Roboto';
                 font-weight: 400;
                 padding: 4px;
@@ -93,7 +87,7 @@
                 margin-right: 7px;
                 display: flex;
                 align-items: center;
-                border: black 1px solid;
+                border: white 1px solid;
 
                 .topbar-logoff {
                     border-radius: 3px;
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 79239d4ea..65da717f8 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -1,58 +1,67 @@
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { observer } from "mobx-react";
 import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { StrCast } from '../../../fields/Types';
 import { Utils } from '../../../Utils';
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { ColorScheme, SettingsManager } from "../../util/SettingsManager";
+import { SettingsManager } from "../../util/SettingsManager";
 import { undoBatch } from "../../util/UndoManager";
+import { Borders, Colors } from "../global/globalEnums";
 import "./TopBar.scss";
-import { Colors, Borders } from "../global/globalEnums";
 
-export const TopBar = () => {
-
-    const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data);
-    return (
-        <div style={{ pointerEvents: "all" }} className="topbar-container">
-            <div className="topbar-bar" style={{ background: Doc.UserDoc().colorScheme === ColorScheme.Dark ? Colors.DARK_GRAY : Colors.LIGHT_GRAY, borderBottom: Borders.STANDARD }}>
-                <div className="topbar-center" >
-                    <div className="topbar-lozenge-dashboard">
-                        <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
-                            value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)}
-                            style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
-                            {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
-                        </select>
-                        <div className="topbar-dashboards">
-                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
-                                style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
-                                <FontAwesomeIcon icon="plus"></FontAwesomeIcon>
-                            </div>
-                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
-                                style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
-                                <FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+/**
+ * REACT TYPE: FUNCTIONAL
+ * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user
+ * and settings and help buttons. Future scope for this bar is to include the collaborators that are on the same Dashboard. 
+ */
+@observer
+export class TopBar extends React.Component {
+    render() {
+        const myDashboards = DocListCast(CurrentUserUtils.MyDashboards.data);
+        return (
+            //TODO:glr Add support for light / dark mode
+            <div style={{ pointerEvents: "all" }} className="topbar-container">
+                <div className="topbar-bar" style={{ background: Colors.DARK_GRAY, borderBottom: Borders.STANDARD }}>
+                    <div className="topbar-center" >
+                        <div className="topbar-lozenge-dashboard">
+                            <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
+                                value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)}
+                                style={{ color: Colors.WHITE }}>
+                                {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
+                            </select>
+                            <div className="topbar-dashboards">
+                                <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
+                                    style={{ color: Colors.WHITE }}>
+                                    <FontAwesomeIcon icon="plus"></FontAwesomeIcon>
+                                </div>
+                                <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
+                                    style={{ color: Colors.WHITE }}>
+                                    <FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
-                <div className="topbar-right" >
-                    <div className="topbar-icon"
-                        style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
-                        <FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
-                    </div>
-                    <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}
-                        style={{ color: Doc.UserDoc().colorScheme === ColorScheme.Dark ? "white" : "black" }}>
-                        <FontAwesomeIcon icon="cog"></FontAwesomeIcon>
-                    </div>
-                    <div className="topbar-lozenge-user">
-                        {`${Doc.CurrentUserEmail}`}
-                        <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
-                            Logoff
+                    <div className="topbar-right" >
+                        <div className="topbar-icon"
+                            style={{ color: Colors.WHITE }}>
+                            <FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
+                        </div>
+                        <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}
+                            style={{ color: Colors.WHITE }}>
+                            <FontAwesomeIcon icon="cog"></FontAwesomeIcon>
+                        </div>
+                        <div className="topbar-lozenge-user">
+                            {`${Doc.CurrentUserEmail}`}
+                            <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+                                Logoff
+                        </div>
                         </div>
                     </div>
-                </div>
 
+                </div >
             </div >
-        </div >
-    );
+        );
+    }
 }
\ No newline at end of file
diff --git a/tslint.json b/tslint.json
index 0056f4266..83255a798 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,6 +1,9 @@
 {
     "linterOptions": {
-        "exclude": ["./src/client/northstar/**", "**/*.js"]
+        "exclude": [
+            "./src/client/northstar/**",
+            "**/*.js"
+        ]
     },
     "rules": {
         "no-return-await": true,
@@ -23,41 +26,7 @@
         ],
         "no-tautology-expression": true,
         "unnecessary-constructor": true
-        // "trailing-comma": [
-        //     true,
-        //     {
-        //         "multiline": "always",
-        //         "singleline": "never"
-        //     }
-        // ],
-        // "ordered-imports": true
-        // "quotemark": [
-        //     true,
-        //     "double",
-        //     "jsx-double",
-        //     "avoid-template",
-        //     "avoid-escape"
-        // ],
-        // "object-literal-shorthand": true,
-        // "object-literal-sort-keys": true,
-        // "align": [
-        //     true,
-        //     "parameters",
-        //     "arguments",
-        //     "statements",
-        //     "members",
-        //     "elements"
-        // ],
-        // "no-void-expression": [
-        //     true,
-        //     "ignore-arrow-function-shorthand"
-        // ],
-        // "no-non-null-assertion": true,
-        // "no-var-keyword": true,
-        // "no-var-requires": true,
     },
     "defaultSeverity": "warning",
-    "jsRules": {
-
-    }
+    "jsRules": {}
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e1707fb76a991d04797a8d97ca34c55db71899cd Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Sat, 31 Jul 2021 05:38:08 -0400
Subject: tab scrollable

---
 src/client/goldenLayout.js               | 3063 +++++++++++++++---------------
 src/client/views/MainView.scss           |    4 +-
 src/client/views/topbar/TopBar.scss      |   52 +-
 src/client/views/topbar/TopBar.tsx       |   22 +-
 src/client/views/topbar/TopBarButton.tsx |   10 -
 5 files changed, 1572 insertions(+), 1579 deletions(-)
 delete mode 100644 src/client/views/topbar/TopBarButton.tsx

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 9cfea7f3f..b118a5f44 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -82,16 +82,16 @@
         return target;
     };
 
-	/**
-	 * This is based on Paul Irish's shim, but looks quite odd in comparison. Why?
-	 * Because
-	 * a) it shouldn't affect the global requestAnimationFrame function
-	 * b) it shouldn't pass on the time that has passed
-	 *
-	 * @param   {Function} fn
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * This is based on Paul Irish's shim, but looks quite odd in comparison. Why?
+     * Because
+     * a) it shouldn't affect the global requestAnimationFrame function
+     * b) it shouldn't pass on the time that has passed
+     *
+     * @param   {Function} fn
+     *
+     * @returns {void}
+     */
     lm.utils.animFrame = function (fn) {
         return (window.requestAnimationFrame ||
             window.webkitRequestAnimationFrame ||
@@ -178,16 +178,16 @@
             .replace('.', '');
     };
 
-	/**
-	 * A basic XSS filter. It is ultimately up to the
-	 * implementing developer to make sure their particular
-	 * applications and usecases are save from cross site scripting attacks
-	 *
-	 * @param   {String} input
-	 * @param    {Boolean} keepTags
-	 *
-	 * @returns {String} filtered input
-	 */
+    /**
+     * A basic XSS filter. It is ultimately up to the
+     * implementing developer to make sure their particular
+     * applications and usecases are save from cross site scripting attacks
+     *
+     * @param   {String} input
+     * @param    {Boolean} keepTags
+     *
+     * @returns {String} filtered input
+     */
     lm.utils.filterXss = function (input, keepTags) {
 
         var output = input
@@ -206,41 +206,41 @@
         }
     };
 
-	/**
-	 * Removes html tags from a string
-	 *
-	 * @param   {String} input
-	 *
-	 * @returns {String} input without tags
-	 */
+    /**
+     * Removes html tags from a string
+     *
+     * @param   {String} input
+     *
+     * @returns {String} input without tags
+     */
     lm.utils.stripTags = function (input) {
         return $.trim(input.replace(/(<([^>]+)>)/ig, ''));
     };
-	/**
-	 * A generic and very fast EventEmitter
-	 * implementation. On top of emitting the
-	 * actual event it emits an
-	 *
-	 * lm.utils.EventEmitter.ALL_EVENT
-	 *
-	 * event for every event triggered. This allows
-	 * to hook into it and proxy events forwards
-	 *
-	 * @constructor
-	 */
+    /**
+     * A generic and very fast EventEmitter
+     * implementation. On top of emitting the
+     * actual event it emits an
+     *
+     * lm.utils.EventEmitter.ALL_EVENT
+     *
+     * event for every event triggered. This allows
+     * to hook into it and proxy events forwards
+     *
+     * @constructor
+     */
     lm.utils.EventEmitter = function () {
         this._mSubscriptions = {};
         this._mSubscriptions[lm.utils.EventEmitter.ALL_EVENT] = [];
 
-		/**
-		 * Listen for events
-		 *
-		 * @param   {String} sEvent    The name of the event to listen to
-		 * @param   {Function} fCallback The callback to execute when the event occurs
-		 * @param   {[Object]} oContext The value of the this pointer within the callback function
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Listen for events
+         *
+         * @param   {String} sEvent    The name of the event to listen to
+         * @param   {Function} fCallback The callback to execute when the event occurs
+         * @param   {[Object]} oContext The value of the this pointer within the callback function
+         *
+         * @returns {void}
+         */
         this.on = function (sEvent, fCallback, oContext) {
             if (!lm.utils.isFunction(fCallback)) {
                 throw new Error('Tried to listen to event ' + sEvent + ' with non-function callback ' + fCallback);
@@ -253,14 +253,14 @@
             this._mSubscriptions[sEvent].push({ fn: fCallback, ctx: oContext });
         };
 
-		/**
-		 * Emit an event and notify listeners
-		 *
-		 * @param   {String} sEvent The name of the event
-		 * @param    {Mixed}  various additional arguments that will be passed to the listener
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Emit an event and notify listeners
+         *
+         * @param   {String} sEvent The name of the event
+         * @param    {Mixed}  various additional arguments that will be passed to the listener
+         *
+         * @returns {void}
+         */
         this.emit = function (sEvent) {
             var i, ctx, args;
 
@@ -286,15 +286,15 @@
             }
         };
 
-		/**
-		 * Removes a listener for an event, or all listeners if no callback and context is provided.
-		 *
-		 * @param   {String} sEvent    The name of the event
-		 * @param   {Function} fCallback The previously registered callback method (optional)
-		 * @param   {Object} oContext  The previously registered context (optional)
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Removes a listener for an event, or all listeners if no callback and context is provided.
+         *
+         * @param   {String} sEvent    The name of the event
+         * @param   {Function} fCallback The previously registered callback method (optional)
+         * @param   {Object} oContext  The previously registered context (optional)
+         *
+         * @returns {void}
+         */
         this.unbind = function (sEvent, fCallback, oContext) {
             if (!this._mSubscriptions[sEvent]) {
                 throw new Error('No subscribtions to unsubscribe for event ' + sEvent);
@@ -318,28 +318,28 @@
             }
         };
 
-		/**
-		 * Alias for unbind
-		 */
+        /**
+         * Alias for unbind
+         */
         this.off = this.unbind;
 
-		/**
-		 * Alias for emit
-		 */
+        /**
+         * Alias for emit
+         */
         this.trigger = this.emit;
     };
 
-	/**
-	 * The name of the event that's triggered for every other event
-	 *
-	 * usage
-	 *
-	 * myEmitter.on( lm.utils.EventEmitter.ALL_EVENT, function( eventName, argsArray ){
-	 * 	//do stuff
-	 * });
-	 *
-	 * @type {String}
-	 */
+    /**
+     * The name of the event that's triggered for every other event
+     *
+     * usage
+     *
+     * myEmitter.on( lm.utils.EventEmitter.ALL_EVENT, function( eventName, argsArray ){
+     * 	//do stuff
+     * });
+     *
+     * @type {String}
+     */
     lm.utils.EventEmitter.ALL_EVENT = '__all';
     lm.utils.DragListener = function (eElement, nButtonCode) {
         lm.utils.EventEmitter.call(this);
@@ -349,14 +349,14 @@
         this._eBody = $(document.body);
         this._nButtonCode = nButtonCode || 0;
 
-		/**
-		 * The delay after which to start the drag in milliseconds
-		 */
+        /**
+         * The delay after which to start the drag in milliseconds
+         */
         this._nDelay = 200;
 
-		/**
-		 * The distance the mouse needs to be moved to qualify as a drag
-		 */
+        /**
+         * The distance the mouse needs to be moved to qualify as a drag
+         */
         this._nDistance = 10;//TODO - works better with delay only
 
         this._nX = 0;
@@ -459,16 +459,16 @@
             };
         }
     });
-	/**
-	 * The main class that will be exposed as GoldenLayout.
-	 *
-	 * @public
-	 * @constructor
-	 * @param {GoldenLayout config} config
-	 * @param {[DOM element container]} container Can be a jQuery selector string or a Dom element. Defaults to body
-	 *
-	 * @returns {VOID}
-	 */
+    /**
+     * The main class that will be exposed as GoldenLayout.
+     *
+     * @public
+     * @constructor
+     * @param {GoldenLayout config} config
+     * @param {[DOM element container]} container Can be a jQuery selector string or a Dom element. Defaults to body
+     *
+     * @returns {VOID}
+     */
     lm.LayoutManager = function (config, container) {
 
         if (!$ || typeof $.noConflict !== 'function') {
@@ -521,59 +521,59 @@
         };
     };
 
-	/**
-	 * Hook that allows to access private classes
-	 */
+    /**
+     * Hook that allows to access private classes
+     */
     lm.LayoutManager.__lm = lm;
 
-	/**
-	 * Takes a GoldenLayout configuration object and
-	 * replaces its keys and values recursively with
-	 * one letter codes
-	 *
-	 * @static
-	 * @public
-	 * @param   {Object} config A GoldenLayout config object
-	 *
-	 * @returns {Object} minified config
-	 */
+    /**
+     * Takes a GoldenLayout configuration object and
+     * replaces its keys and values recursively with
+     * one letter codes
+     *
+     * @static
+     * @public
+     * @param   {Object} config A GoldenLayout config object
+     *
+     * @returns {Object} minified config
+     */
     lm.LayoutManager.minifyConfig = function (config) {
         return (new lm.utils.ConfigMinifier()).minifyConfig(config);
     };
 
-	/**
-	 * Takes a configuration Object that was previously minified
-	 * using minifyConfig and returns its original version
-	 *
-	 * @static
-	 * @public
-	 * @param   {Object} minifiedConfig
-	 *
-	 * @returns {Object} the original configuration
-	 */
+    /**
+     * Takes a configuration Object that was previously minified
+     * using minifyConfig and returns its original version
+     *
+     * @static
+     * @public
+     * @param   {Object} minifiedConfig
+     *
+     * @returns {Object} the original configuration
+     */
     lm.LayoutManager.unminifyConfig = function (config) {
         return (new lm.utils.ConfigMinifier()).unminifyConfig(config);
     };
 
     lm.utils.copy(lm.LayoutManager.prototype, {
 
-		/**
-		 * Register a component with the layout manager. If a configuration node
-		 * of type component is reached it will look up componentName and create the
-		 * associated component
-		 *
-		 *  {
-		 *		type: "component",
-		 *		componentName: "EquityNewsFeed",
-		 *		componentState: { "feedTopic": "us-bluechips" }
-		 *  }
-		 *
-		 * @public
-		 * @param   {String} name
-		 * @param   {Function} constructor
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Register a component with the layout manager. If a configuration node
+         * of type component is reached it will look up componentName and create the
+         * associated component
+         *
+         *  {
+         *		type: "component",
+         *		componentName: "EquityNewsFeed",
+         *		componentState: { "feedTopic": "us-bluechips" }
+         *  }
+         *
+         * @public
+         * @param   {String} name
+         * @param   {Function} constructor
+         *
+         * @returns {void}
+         */
         registerComponent: function (name, constructor) {
             if (typeof constructor !== 'function') {
                 throw new Error('Please register a constructor function');
@@ -586,12 +586,12 @@
             this._components[name] = constructor;
         },
 
-		/**
-		 * Creates a layout configuration object based on the the current state
-		 *
-		 * @public
-		 * @returns {Object} GoldenLayout configuration
-		 */
+        /**
+         * Creates a layout configuration object based on the the current state
+         *
+         * @public
+         * @returns {Object} GoldenLayout configuration
+         */
         toConfig: function (root) {
             var config, next, i;
 
@@ -603,18 +603,18 @@
                 throw new Error('Root must be a ContentItem');
             }
 
-			/*
-			 * settings & labels
-			 */
+            /*
+             * settings & labels
+             */
             config = {
                 settings: lm.utils.copy({}, this.config.settings),
                 dimensions: lm.utils.copy({}, this.config.dimensions),
                 labels: lm.utils.copy({}, this.config.labels)
             };
 
-			/*
-			 * Content
-			 */
+            /*
+             * Content
+             */
             config.content = [];
             next = function (configNode, item) {
                 var key, i;
@@ -641,30 +641,30 @@
                 next(config, this.root);
             }
 
-			/*
-			 * Retrieve config for subwindows
-			 */
+            /*
+             * Retrieve config for subwindows
+             */
             this._$reconcilePopoutWindows();
             config.openPopouts = [];
             for (i = 0; i < this.openPopouts.length; i++) {
                 config.openPopouts.push(this.openPopouts[i].toConfig());
             }
 
-			/*
-			 * Add maximised item
-			 */
+            /*
+             * Add maximised item
+             */
             config.maximisedItemId = this._maximisedItem ? '__glMaximised' : null;
             return config;
         },
 
-		/**
-		 * Returns a previously registered component
-		 *
-		 * @public
-		 * @param   {String} name The name used
-		 *
-		 * @returns {Function}
-		 */
+        /**
+         * Returns a previously registered component
+         *
+         * @public
+         * @param   {String} name The name used
+         *
+         * @returns {Function}
+         */
         getComponent: function (name) {
             if (this._components[name] === undefined) {
                 throw new lm.errors.ConfigurationError('Unknown component "' + name + '"');
@@ -673,44 +673,44 @@
             return this._components[name];
         },
 
-		/**
-		 * Creates the actual layout. Must be called after all initial components
-		 * are registered. Recurses through the configuration and sets up
-		 * the item tree.
-		 *
-		 * If called before the document is ready it adds itself as a listener
-		 * to the document.ready event
-		 *
-		 * @public
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Creates the actual layout. Must be called after all initial components
+         * are registered. Recurses through the configuration and sets up
+         * the item tree.
+         *
+         * If called before the document is ready it adds itself as a listener
+         * to the document.ready event
+         *
+         * @public
+         *
+         * @returns {void}
+         */
         init: function () {
 
-			/**
-			 * Create the popout windows straight away. If popouts are blocked
-			 * an error is thrown on the same 'thread' rather than a timeout and can
-			 * be caught. This also prevents any further initilisation from taking place.
-			 */
+            /**
+             * Create the popout windows straight away. If popouts are blocked
+             * an error is thrown on the same 'thread' rather than a timeout and can
+             * be caught. This also prevents any further initilisation from taking place.
+             */
             if (this._subWindowsCreated === false) {
                 this._createSubWindows();
                 this._subWindowsCreated = true;
             }
 
 
-			/**
-			 * If the document isn't ready yet, wait for it.
-			 */
+            /**
+             * If the document isn't ready yet, wait for it.
+             */
             if (document.readyState === 'loading' || document.body === null) {
                 $(document).ready(lm.utils.fnBind(this.init, this));
                 return;
             }
 
-			/**
-			 * If this is a subwindow, wait a few milliseconds for the original
-			 * page's js calls to be executed, then replace the bodies content
-			 * with GoldenLayout
-			 */
+            /**
+             * If this is a subwindow, wait a few milliseconds for the original
+             * page's js calls to be executed, then replace the bodies content
+             * with GoldenLayout
+             */
             if (this.isSubWindow === true && this._creationTimeoutPassed === false) {
                 setTimeout(lm.utils.fnBind(this.init, this), 7);
                 this._creationTimeoutPassed = true;
@@ -732,15 +732,15 @@
             this.emit('initialised');
         },
 
-		/**
-		 * Updates the layout managers size
-		 *
-		 * @public
-		 * @param   {[int]} width  height in pixels
-		 * @param   {[int]} height width in pixels
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Updates the layout managers size
+         *
+         * @public
+         * @param   {[int]} width  height in pixels
+         * @param   {[int]} height width in pixels
+         *
+         * @returns {void}
+         */
         updateSize: function (width, height) {
             if (arguments.length === 2) {
                 this.width = width;
@@ -763,13 +763,13 @@
             }
         },
 
-		/**
-		 * Destroys the LayoutManager instance itself as well as every ContentItem
-		 * within it. After this is called nothing should be left of the LayoutManager.
-		 *
-		 * @public
-		 * @returns {void}
-		 */
+        /**
+         * Destroys the LayoutManager instance itself as well as every ContentItem
+         * within it. After this is called nothing should be left of the LayoutManager.
+         *
+         * @public
+         * @returns {void}
+         */
         destroy: function () {
             if (this.isInitialised === false) {
                 return;
@@ -793,16 +793,16 @@
             this._dragSources = [];
         },
 
-		/**
-		 * Recursively creates new item tree structures based on a provided
-		 * ItemConfiguration object
-		 *
-		 * @public
-		 * @param   {Object} config ItemConfig
-		 * @param   {[ContentItem]} parent The item the newly created item should be a child of
-		 *
-		 * @returns {lm.items.ContentItem}
-		 */
+        /**
+         * Recursively creates new item tree structures based on a provided
+         * ItemConfiguration object
+         *
+         * @public
+         * @param   {Object} config ItemConfig
+         * @param   {[ContentItem]} parent The item the newly created item should be a child of
+         *
+         * @returns {lm.items.ContentItem}
+         */
         createContentItem: function (config, parent) {
             var typeErrorMsg, contentItem;
 
@@ -823,9 +823,9 @@
             }
 
 
-			/**
-			 * We add an additional stack around every component that's not within a stack anyways.
-			 */
+            /**
+             * We add an additional stack around every component that's not within a stack anyways.
+             */
             if (
                 // If this is a component
                 config.type === 'component' &&
@@ -851,17 +851,17 @@
             return contentItem;
         },
 
-		/**
-		 * Creates a popout window with the specified content and dimensions
-		 *
-		 * @param   {Object|lm.itemsAbstractContentItem} configOrContentItem
-		 * @param   {[Object]} dimensions A map with width, height, left and top
-		 * @param    {[String]} parentId the id of the element this item will be appended to
-		 *                             when popIn is called
-		 * @param    {[Number]} indexInParent The position of this item within its parent element
+        /**
+         * Creates a popout window with the specified content and dimensions
+         *
+         * @param   {Object|lm.itemsAbstractContentItem} configOrContentItem
+         * @param   {[Object]} dimensions A map with width, height, left and top
+         * @param    {[String]} parentId the id of the element this item will be appended to
+         *                             when popIn is called
+         * @param    {[Number]} indexInParent The position of this item within its parent element
 	
-		 * @returns {lm.controls.BrowserPopout}
-		 */
+         * @returns {lm.controls.BrowserPopout}
+         */
         createPopout: function (configOrContentItem, dimensions, parentId, indexInParent) {
             var config = configOrContentItem,
                 isItem = configOrContentItem instanceof lm.items.AbstractContentItem,
@@ -879,14 +879,14 @@
                 config = this.toConfig(configOrContentItem).content;
                 parentId = lm.utils.getUniqueId();
 
-				/**
-				 * If the item is the only component within a stack or for some
-				 * other reason the only child of its parent the parent will be destroyed
-				 * when the child is removed.
-				 *
-				 * In order to support this we move up the tree until we find something
-				 * that will remain after the item is being popped out
-				 */
+                /**
+                 * If the item is the only component within a stack or for some
+                 * other reason the only child of its parent the parent will be destroyed
+                 * when the child is removed.
+                 *
+                 * In order to support this we move up the tree until we find something
+                 * that will remain after the item is being popped out
+                 */
                 parent = configOrContentItem.parent;
                 child = configOrContentItem;
                 while (parent.contentItems.length === 1 && !parent.isRoot) {
@@ -946,16 +946,16 @@
             return browserPopout;
         },
 
-		/**
-		 * Attaches DragListener to any given DOM element
-		 * and turns it into a way of creating new ContentItems
-		 * by 'dragging' the DOM element into the layout
-		 *
-		 * @param   {jQuery DOM element} element
-		 * @param   {Object|Function} itemConfig for the new item to be created, or a function which will provide it
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Attaches DragListener to any given DOM element
+         * and turns it into a way of creating new ContentItems
+         * by 'dragging' the DOM element into the layout
+         *
+         * @param   {jQuery DOM element} element
+         * @param   {Object|Function} itemConfig for the new item to be created, or a function which will provide it
+         *
+         * @returns {void}
+         */
         createDragSource: function (element, itemConfig) {
             this.config.settings.constrainDragToContainer = false;
             var dragSource = new lm.controls.DragSource($(element), itemConfig, this);
@@ -964,17 +964,17 @@
             return dragSource;
         },
 
-		/**
-		 * Programmatically selects an item. This deselects
-		 * the currently selected item, selects the specified item
-		 * and emits a selectionChanged event
-		 *
-		 * @param   {lm.item.AbstractContentItem} item#
-		 * @param   {[Boolean]} _$silent Wheather to notify the item of its selection
-		 * @event    selectionChanged
-		 *
-		 * @returns {VOID}
-		 */
+        /**
+         * Programmatically selects an item. This deselects
+         * the currently selected item, selects the specified item
+         * and emits a selectionChanged event
+         *
+         * @param   {lm.item.AbstractContentItem} item#
+         * @param   {[Boolean]} _$silent Wheather to notify the item of its selection
+         * @event    selectionChanged
+         *
+         * @returns {VOID}
+         */
         selectItem: function (item, _$silent) {
 
             if (this.config.settings.selectionEnabled !== true) {
@@ -998,9 +998,9 @@
             this.emit('selectionChanged', item);
         },
 
-		/*************************
-		 * PACKAGE PRIVATE
-		 *************************/
+        /*************************
+         * PACKAGE PRIVATE
+         *************************/
         _$maximiseItem: function (contentItem) {
             if (this._maximisedItem !== null) {
                 this._$minimiseItem(this._maximisedItem);
@@ -1028,20 +1028,20 @@
             this.emit('stateChanged');
         },
 
-		/**
-		 * This method is used to get around sandboxed iframe restrictions.
-		 * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute
-		 * (as is the case with codepens) the parent window is forbidden from calling certain
-		 * methods on the child, such as window.close() or setting document.location.href.
-		 *
-		 * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call
-		 * _$closeWindow on the child window's gl instance which (after a timeout to disconnect
-		 * the invoking method from the close call) closes itself.
-		 *
-		 * @packagePrivate
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * This method is used to get around sandboxed iframe restrictions.
+         * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute
+         * (as is the case with codepens) the parent window is forbidden from calling certain
+         * methods on the child, such as window.close() or setting document.location.href.
+         *
+         * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call
+         * _$closeWindow on the child window's gl instance which (after a timeout to disconnect
+         * the invoking method from the close call) closes itself.
+         *
+         * @packagePrivate
+         *
+         * @returns {void}
+         */
         _$closeWindow: function () {
             window.setTimeout(function () {
                 window.close();
@@ -1088,13 +1088,13 @@
             var i, area, allContentItems = this._getAllContentItems();
             this._itemAreas = [];
 
-			/**
-			 * If the last item is dragged out, highlight the entire container size to
-			 * allow to re-drop it. allContentItems[ 0 ] === this.root at this point
-			 *
-			 * Don't include root into the possible drop areas though otherwise since it
-			 * will used for every gap in the layout, e.g. splitters
-			 */
+            /**
+             * If the last item is dragged out, highlight the entire container size to
+             * allow to re-drop it. allContentItems[ 0 ] === this.root at this point
+             *
+             * Don't include root into the possible drop areas though otherwise since it
+             * will used for every gap in the layout, e.g. splitters
+             */
             if (allContentItems.length === 1) {
                 this._itemAreas.push(this.root._$getArea());
                 return;
@@ -1124,18 +1124,18 @@
             }
         },
 
-		/**
-		 * Takes a contentItem or a configuration and optionally a parent
-		 * item and returns an initialised instance of the contentItem.
-		 * If the contentItem is a function, it is first called
-		 *
-		 * @packagePrivate
-		 *
-		 * @param   {lm.items.AbtractContentItem|Object|Function} contentItemOrConfig
-		 * @param   {lm.items.AbtractContentItem} parent Only necessary when passing in config
-		 *
-		 * @returns {lm.items.AbtractContentItem}
-		 */
+        /**
+         * Takes a contentItem or a configuration and optionally a parent
+         * item and returns an initialised instance of the contentItem.
+         * If the contentItem is a function, it is first called
+         *
+         * @packagePrivate
+         *
+         * @param   {lm.items.AbtractContentItem|Object|Function} contentItemOrConfig
+         * @param   {lm.items.AbtractContentItem} parent Only necessary when passing in config
+         *
+         * @returns {lm.items.AbtractContentItem}
+         */
         _$normalizeContentItem: function (contentItemOrConfig, parent) {
             if (!contentItemOrConfig) {
                 throw new Error('No content item defined');
@@ -1158,15 +1158,15 @@
             }
         },
 
-		/**
-		 * Iterates through the array of open popout windows and removes the ones
-		 * that are effectively closed. This is necessary due to the lack of reliably
-		 * listening for window.close / unload events in a cross browser compatible fashion.
-		 *
-		 * @packagePrivate
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Iterates through the array of open popout windows and removes the ones
+         * that are effectively closed. This is necessary due to the lack of reliably
+         * listening for window.close / unload events in a cross browser compatible fashion.
+         *
+         * @packagePrivate
+         *
+         * @returns {void}
+         */
         _$reconcilePopoutWindows: function () {
             var openPopouts = [], i;
 
@@ -1185,17 +1185,17 @@
 
         },
 
-		/***************************
-		 * PRIVATE
-		 ***************************/
-		/**
-		 * Returns a flattened array of all content items,
-		 * regardles of level or type
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /***************************
+         * PRIVATE
+         ***************************/
+        /**
+         * Returns a flattened array of all content items,
+         * regardles of level or type
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _getAllContentItems: function () {
             var allContentItems = [];
 
@@ -1214,13 +1214,13 @@
             return allContentItems;
         },
 
-		/**
-		 * Binds to DOM/BOM events on init
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Binds to DOM/BOM events on init
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _bindEvents: function () {
             if (this._isFullPage) {
                 $(window).resize(this._resizeFunction);
@@ -1228,27 +1228,27 @@
             $(window).on('unload beforeunload', this._unloadFunction);
         },
 
-		/**
-		 * Debounces resize events
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Debounces resize events
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _onResize: function () {
             clearTimeout(this._resizeTimeoutId);
             this._resizeTimeoutId = setTimeout(lm.utils.fnBind(this.updateSize, this), 100);
         },
 
-		/**
-		 * Extends the default config with the user specific settings and applies
-		 * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode)
-		 * that deals with the extension of item configs
-		 *
-		 * @param   {Object} config
-		 * @static
-		 * @returns {Object} config
-		 */
+        /**
+         * Extends the default config with the user specific settings and applies
+         * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode)
+         * that deals with the extension of item configs
+         *
+         * @param   {Object} config
+         * @static
+         * @returns {Object} config
+         */
         _createConfig: function (config) {
             var windowConfigKey = lm.utils.getQueryStringParam('gl-window');
 
@@ -1283,14 +1283,14 @@
             return config;
         },
 
-		/**
-		 * This is executed when GoldenLayout detects that it is run
-		 * within a previously opened popout window.
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * This is executed when GoldenLayout detects that it is run
+         * within a previously opened popout window.
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _adjustToWindowMode: function () {
             var popInButton = $('<div class="lm_popin" title="' + this.config.labels.popin + '">' +
                 '<div class="lm_icon"></div>' +
@@ -1310,26 +1310,26 @@
                 .css('visibility', 'visible')
                 .append(popInButton);
 
-			/*
-			 * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around
-			 * slickgrid's "Cannot find stylesheet." bug in chrome
-			 */
+            /*
+             * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around
+             * slickgrid's "Cannot find stylesheet." bug in chrome
+             */
             var x = document.body.offsetHeight; // jshint ignore:line
 
-			/*
-			 * Expose this instance on the window object
-			 * to allow the opening window to interact with
-			 * it
-			 */
+            /*
+             * Expose this instance on the window object
+             * to allow the opening window to interact with
+             * it
+             */
             window.__glInstance = this;
         },
 
-		/**
-		 * Creates Subwindows (if there are any). Throws an error
-		 * if popouts are blocked.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Creates Subwindows (if there are any). Throws an error
+         * if popouts are blocked.
+         *
+         * @returns {void}
+         */
         _createSubWindows: function () {
             var i, popout;
 
@@ -1345,13 +1345,13 @@
             }
         },
 
-		/**
-		 * Determines what element the layout will be created in
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Determines what element the layout will be created in
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _setContainer: function () {
             var container = $(this.container || 'body');
 
@@ -1377,13 +1377,13 @@
             this.container = container;
         },
 
-		/**
-		 * Kicks of the initial, recursive creation chain
-		 *
-		 * @param   {Object} config GoldenLayout Config
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Kicks of the initial, recursive creation chain
+         *
+         * @param   {Object} config GoldenLayout Config
+         *
+         * @returns {void}
+         */
         _create: function (config) {
             var errorMsg;
 
@@ -1410,12 +1410,12 @@
             }
         },
 
-		/**
-		 * Called when the window is closed or the user navigates away
-		 * from the page
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Called when the window is closed or the user navigates away
+         * from the page
+         *
+         * @returns {void}
+         */
         _onUnload: function () {
             if (this.config.settings.closePopoutsOnUnload === true) {
                 for (var i = 0; i < this.openPopouts.length; i++) {
@@ -1424,11 +1424,11 @@
             }
         },
 
-		/**
-		 * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth.
+         *
+         * @returns {void}
+         */
         _adjustColumnsResponsive: function () {
 
             // If there is no min width set, or not content items, do nothing.
@@ -1470,21 +1470,21 @@
             this._updatingColumnsResponsive = false;
         },
 
-		/**
-		 * Determines if responsive layout should be used.
-		 *
-		 * @returns {bool} - True if responsive layout should be used; otherwise false.
-		 */
+        /**
+         * Determines if responsive layout should be used.
+         *
+         * @returns {bool} - True if responsive layout should be used; otherwise false.
+         */
         _useResponsiveLayout: function () {
             return this.config.settings && (this.config.settings.responsiveMode == 'always' || (this.config.settings.responsiveMode == 'onload' && this._firstLoad));
         },
 
-		/**
-		 * Adds all children of a node to another container recursively.
-		 * @param {object} container - Container to add child content items to.
-		 * @param {object} node - Node to search for content items.
-		 * @returns {void}
-		 */
+        /**
+         * Adds all children of a node to another container recursively.
+         * @param {object} container - Container to add child content items to.
+         * @param {object} node - Node to search for content items.
+         * @returns {void}
+         */
         _addChildContentItemsToContainer: function (container, node) {
             if (node.type === 'stack') {
                 node.contentItems.forEach(function (item) {
@@ -1499,10 +1499,10 @@
             }
         },
 
-		/**
-		 * Finds all the stack containers.
-		 * @returns {array} - The found stack containers.
-		 */
+        /**
+         * Finds all the stack containers.
+         * @returns {array} - The found stack containers.
+         */
         _findAllStackContainers: function () {
             var stackContainers = [];
             this._findAllStackContainersRecursive(stackContainers, this.root);
@@ -1510,14 +1510,14 @@
             return stackContainers;
         },
 
-		/**
-		 * Finds all the stack containers.
-		 *
-		 * @param {array} - Set of containers to populate.
-		 * @param {object} - Current node to process.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Finds all the stack containers.
+         *
+         * @param {array} - Set of containers to populate.
+         * @param {object} - Current node to process.
+         *
+         * @returns {void}
+         */
         _findAllStackContainersRecursive: function (stackContainers, node) {
             node.contentItems.forEach(lm.utils.fnBind(function (item) {
                 if (item.type == 'stack') {
@@ -1530,9 +1530,9 @@
         }
     });
 
-	/**
-	 * Expose the Layoutmanager as the single entrypoint using UMD
-	 */
+    /**
+     * Expose the Layoutmanager as the single entrypoint using UMD
+     */
     (function () {
         /* global define */
         if (typeof define === 'function' && define.amd) {
@@ -1567,7 +1567,7 @@
             showCloseIcon: true,
             responsiveMode: 'onload', // Can be onload, always, or none.
             tabOverlapAllowance: 0, // maximum pixel overlap per tab
-            reorderOnTabMenuClick: true,
+            reorderOnTabMenuClick: false, //do not reorder! - horizontal scroll
             tabControlOffset: 10
         },
         dimensions: {
@@ -1575,7 +1575,7 @@
             borderGrabWidth: 5,
             minItemHeight: 10,
             minItemWidth: 10,
-            headerHeight: 20,
+            headerHeight: 22,
             dragProxyWidth: 300,
             dragProxyHeight: 200
         },
@@ -1611,36 +1611,36 @@
 
     lm.utils.copy(lm.container.ItemContainer.prototype, {
 
-		/**
-		 * Get the inner DOM element the container's content
-		 * is intended to live in
-		 *
-		 * @returns {DOM element}
-		 */
+        /**
+         * Get the inner DOM element the container's content
+         * is intended to live in
+         *
+         * @returns {DOM element}
+         */
         getElement: function () {
             return this._contentElement;
         },
 
-		/**
-		 * Hide the container. Notifies the containers content first
-		 * and then hides the DOM node. If the container is already hidden
-		 * this should have no effect
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Hide the container. Notifies the containers content first
+         * and then hides the DOM node. If the container is already hidden
+         * this should have no effect
+         *
+         * @returns {void}
+         */
         hide: function () {
             this.emit('hide');
             this.isHidden = true;
             this._element.hide();
         },
 
-		/**
-		 * Shows a previously hidden container. Notifies the
-		 * containers content first and then shows the DOM element.
-		 * If the container is already visible this has no effect.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Shows a previously hidden container. Notifies the
+         * containers content first and then shows the DOM element.
+         * If the container is already visible this has no effect.
+         *
+         * @returns {void}
+         */
         show: function () {
             this.emit('show');
             this.isHidden = false;
@@ -1651,19 +1651,19 @@
             }
         },
 
-		/**
-		 * Set the size from within the container. Traverses up
-		 * the item tree until it finds a row or column element
-		 * and resizes its items accordingly.
-		 *
-		 * If this container isn't a descendant of a row or column
-		 * it returns false
-		 * @todo  Rework!!!
-		 * @param {Number} width  The new width in pixel
-		 * @param {Number} height The new height in pixel
-		 *
-		 * @returns {Boolean} resizeSuccesful
-		 */
+        /**
+         * Set the size from within the container. Traverses up
+         * the item tree until it finds a row or column element
+         * and resizes its items accordingly.
+         *
+         * If this container isn't a descendant of a row or column
+         * it returns false
+         * @todo  Rework!!!
+         * @param {Number} width  The new width in pixel
+         * @param {Number} height The new height in pixel
+         *
+         * @returns {Boolean} resizeSuccesful
+         */
         setSize: function (width, height) {
             var rowOrColumn = this.parent,
                 rowOrColumnChild = this,
@@ -1679,9 +1679,9 @@
                 rowOrColumn = rowOrColumn.parent;
 
 
-				/**
-				 * No row or column has been found
-				 */
+                /**
+                 * No row or column has been found
+                 */
                 if (rowOrColumn.isRoot) {
                     return false;
                 }
@@ -1707,13 +1707,13 @@
             return true;
         },
 
-		/**
-		 * Closes the container if it is closable. Can be called by
-		 * both the component within at as well as the contentItem containing
-		 * it. Emits a close event before the container itself is closed.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Closes the container if it is closable. Can be called by
+         * both the component within at as well as the contentItem containing
+         * it. Emits a close event before the container itself is closed.
+         *
+         * @returns {void}
+         */
         close: function () {
             if (this._config.isClosable) {
                 this.emit('close');
@@ -1721,55 +1721,55 @@
             }
         },
 
-		/**
-		 * Returns the current state object
-		 *
-		 * @returns {Object} state
-		 */
+        /**
+         * Returns the current state object
+         *
+         * @returns {Object} state
+         */
         getState: function () {
             return this._config.componentState;
         },
 
-		/**
-		 * Merges the provided state into the current one
-		 *
-		 * @param   {Object} state
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Merges the provided state into the current one
+         *
+         * @param   {Object} state
+         *
+         * @returns {void}
+         */
         extendState: function (state) {
             this.setState($.extend(true, this.getState(), state));
         },
 
-		/**
-		 * Notifies the layout manager of a stateupdate
-		 *
-		 * @param {serialisable} state
-		 */
+        /**
+         * Notifies the layout manager of a stateupdate
+         *
+         * @param {serialisable} state
+         */
         setState: function (state) {
             this._config.componentState = state;
             this.parent.emitBubblingEvent('stateChanged');
         },
 
-		/**
-		 * Set's the components title
-		 *
-		 * @param {String} title
-		 */
+        /**
+         * Set's the components title
+         *
+         * @param {String} title
+         */
         setTitle: function (title) {
             this.parent.setTitle(title);
         },
 
-		/**
-		 * Set's the containers size. Called by the container's component.
-		 * To set the size programmatically from within the container please
-		 * use the public setSize method
-		 *
-		 * @param {[Int]} width  in px
-		 * @param {[Int]} height in px
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Set's the containers size. Called by the container's component.
+         * To set the size programmatically from within the container please
+         * use the public setSize method
+         *
+         * @param {[Int]} width  in px
+         * @param {[Int]} height in px
+         *
+         * @returns {void}
+         */
         _$setSize: function (width, height) {
             if (width !== this.width || height !== this.height) {
                 this.width = width;
@@ -1784,22 +1784,22 @@
         }
     });
 
-	/**
-	 * Pops a content item out into a new browser window.
-	 * This is achieved by
-	 *
-	 *    - Creating a new configuration with the content item as root element
-	 *    - Serializing and minifying the configuration
-	 *    - Opening the current window's URL with the configuration as a GET parameter
-	 *    - GoldenLayout when opened in the new window will look for the GET parameter
-	 *      and use it instead of the provided configuration
-	 *
-	 * @param {Object} config GoldenLayout item config
-	 * @param {Object} dimensions A map with width, height, top and left
-	 * @param {String} parentId The id of the element the item will be appended to on popIn
-	 * @param {Number} indexInParent The position of this element within its parent
-	 * @param {lm.LayoutManager} layoutManager
-	 */
+    /**
+     * Pops a content item out into a new browser window.
+     * This is achieved by
+     *
+     *    - Creating a new configuration with the content item as root element
+     *    - Serializing and minifying the configuration
+     *    - Opening the current window's URL with the configuration as a GET parameter
+     *    - GoldenLayout when opened in the new window will look for the GET parameter
+     *      and use it instead of the provided configuration
+     *
+     * @param {Object} config GoldenLayout item config
+     * @param {Object} dimensions A map with width, height, top and left
+     * @param {String} parentId The id of the element the item will be appended to on popIn
+     * @param {Number} indexInParent The position of this element within its parent
+     * @param {lm.LayoutManager} layoutManager
+     */
     lm.controls.BrowserPopout = function (config, dimensions, parentId, indexInParent, layoutManager) {
         lm.utils.EventEmitter.call(this);
         this.isInitialised = false;
@@ -1853,10 +1853,10 @@
             }
         },
 
-		/**
-		 * Returns the popped out item to its original position. If the original
-		 * parent isn't available anymore it falls back to the layout's topmost element
-		 */
+        /**
+         * Returns the popped out item to its original position. If the original
+         * parent isn't available anymore it falls back to the layout's topmost element
+         */
         popIn: function () {
             var childConfig,
                 parentItem,
@@ -1864,22 +1864,22 @@
 
             if (this._parentId) {
 
-				/*
-				 * The $.extend call seems a bit pointless, but it's crucial to
-				 * copy the config returned by this.getGlInstance().toConfig()
-				 * onto a new object. Internet Explorer keeps the references
-				 * to objects on the child window, resulting in the following error
-				 * once the child window is closed:
-				 *
-				 * The callee (server [not server application]) is not available and disappeared
-				 */
+                /*
+                 * The $.extend call seems a bit pointless, but it's crucial to
+                 * copy the config returned by this.getGlInstance().toConfig()
+                 * onto a new object. Internet Explorer keeps the references
+                 * to objects on the child window, resulting in the following error
+                 * once the child window is closed:
+                 *
+                 * The callee (server [not server application]) is not available and disappeared
+                 */
                 childConfig = $.extend(true, {}, this.getGlInstance().toConfig()).content[0];
                 parentItem = this._layoutManager.root.getItemsById(this._parentId)[0];
 
-				/*
-				 * Fallback if parentItem is not available. Either add it to the topmost
-				 * item or make it the topmost item if the layout is empty
-				 */
+                /*
+                 * Fallback if parentItem is not available. Either add it to the topmost
+                 * item or make it the topmost item if the layout is empty
+                 */
                 if (!parentItem) {
                     if (this._layoutManager.root.contentItems.length > 0) {
                         parentItem = this._layoutManager.root.contentItems[0];
@@ -1894,28 +1894,28 @@
             this.close();
         },
 
-		/**
-		 * Creates the URL and window parameter
-		 * and opens a new window
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Creates the URL and window parameter
+         * and opens a new window
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _createWindow: function () {
             var checkReadyInterval,
                 url = this._createUrl(),
 
-				/**
-				 * Bogus title to prevent re-usage of existing window with the
-				 * same title. The actual title will be set by the new window's
-				 * GoldenLayout instance if it detects that it is in subWindowMode
-				 */
+                /**
+                 * Bogus title to prevent re-usage of existing window with the
+                 * same title. The actual title will be set by the new window's
+                 * GoldenLayout instance if it detects that it is in subWindowMode
+                 */
                 title = Math.floor(Math.random() * 1000000).toString(36),
 
-				/**
-				 * The options as used in the window.open string
-				 */
+                /**
+                 * The options as used in the window.open string
+                 */
                 options = this._serializeWindowOptions({
                     width: this._dimensions.width,
                     height: this._dimensions.height,
@@ -1946,12 +1946,12 @@
                 .on('load', lm.utils.fnBind(this._positionWindow, this))
                 .on('unload beforeunload', lm.utils.fnBind(this._onClose, this));
 
-			/**
-			 * Polling the childwindow to find out if GoldenLayout has been initialised
-			 * doesn't seem optimal, but the alternatives - adding a callback to the parent
-			 * window or raising an event on the window object - both would introduce knowledge
-			 * about the parent to the child window which we'd rather avoid
-			 */
+            /**
+             * Polling the childwindow to find out if GoldenLayout has been initialised
+             * doesn't seem optimal, but the alternatives - adding a callback to the parent
+             * window or raising an event on the window object - both would introduce knowledge
+             * about the parent to the child window which we'd rather avoid
+             */
             checkReadyInterval = setInterval(lm.utils.fnBind(function () {
                 if (this._popoutWindow.__glInstance && this._popoutWindow.__glInstance.isInitialised) {
                     this._onInitialised();
@@ -1960,13 +1960,13 @@
             }, this), 10);
         },
 
-		/**
-		 * Serialises a map of key:values to a window options string
-		 *
-		 * @param   {Object} windowOptions
-		 *
-		 * @returns {String} serialised window options
-		 */
+        /**
+         * Serialises a map of key:values to a window options string
+         *
+         * @param   {Object} windowOptions
+         *
+         * @returns {String} serialised window options
+         */
         _serializeWindowOptions: function (windowOptions) {
             var windowOptionsString = [], key;
 
@@ -1977,12 +1977,12 @@
             return windowOptionsString.join(',');
         },
 
-		/**
-		 * Creates the URL for the new window, including the
-		 * config GET parameter
-		 *
-		 * @returns {String} URL
-		 */
+        /**
+         * Creates the URL for the new window, including the
+         * config GET parameter
+         *
+         * @returns {String} URL
+         */
         _createUrl: function () {
             var config = { content: this._config },
                 storageKey = 'gl-window-config-' + lm.utils.getUniqueId(),
@@ -2008,57 +2008,57 @@
             }
         },
 
-		/**
-		 * Move the newly created window roughly to
-		 * where the component used to be.
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Move the newly created window roughly to
+         * where the component used to be.
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _positionWindow: function () {
             this._popoutWindow.moveTo(this._dimensions.left, this._dimensions.top);
             this._popoutWindow.focus();
         },
 
-		/**
-		 * Callback when the new window is opened and the GoldenLayout instance
-		 * within it is initialised
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Callback when the new window is opened and the GoldenLayout instance
+         * within it is initialised
+         *
+         * @returns {void}
+         */
         _onInitialised: function () {
             this.isInitialised = true;
             this.getGlInstance().on('popIn', this.popIn, this);
             this.emit('initialised');
         },
 
-		/**
-		 * Invoked 50ms after the window unload event
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Invoked 50ms after the window unload event
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _onClose: function () {
             setTimeout(lm.utils.fnBind(this.emit, this, ['closed']), 50);
         }
     });
-	/**
-	 * This class creates a temporary container
-	 * for the component whilst it is being dragged
-	 * and handles drag events
-	 *
-	 * @constructor
-	 * @private
-	 *
-	 * @param {Number} x              The initial x position
-	 * @param {Number} y              The initial y position
-	 * @param {lm.utils.DragListener} dragListener
-	 * @param {lm.LayoutManager} layoutManager
-	 * @param {lm.item.AbstractContentItem} contentItem
-	 * @param {lm.item.AbstractContentItem} originalParent
-	 */
+    /**
+     * This class creates a temporary container
+     * for the component whilst it is being dragged
+     * and handles drag events
+     *
+     * @constructor
+     * @private
+     *
+     * @param {Number} x              The initial x position
+     * @param {Number} y              The initial y position
+     * @param {lm.utils.DragListener} dragListener
+     * @param {lm.LayoutManager} layoutManager
+     * @param {lm.item.AbstractContentItem} contentItem
+     * @param {lm.item.AbstractContentItem} originalParent
+     */
     lm.controls.DragProxy = function (x, y, dragListener, layoutManager, contentItem, originalParent) {
 
         lm.utils.EventEmitter.call(this);
@@ -2120,19 +2120,19 @@
 
     lm.utils.copy(lm.controls.DragProxy.prototype, {
 
-		/**
-		 * Callback on every mouseMove event during a drag. Determines if the drag is
-		 * still within the valid drag area and calls the layoutManager to highlight the
-		 * current drop area
-		 *
-		 * @param   {Number} offsetX The difference from the original x position in px
-		 * @param   {Number} offsetY The difference from the original y position in px
-		 * @param   {jQuery DOM event} event
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Callback on every mouseMove event during a drag. Determines if the drag is
+         * still within the valid drag area and calls the layoutManager to highlight the
+         * current drop area
+         *
+         * @param   {Number} offsetX The difference from the original x position in px
+         * @param   {Number} offsetY The difference from the original y position in px
+         * @param   {jQuery DOM event} event
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _onDrag: function (offsetX, offsetY, event) {
 
             event = event.originalEvent && event.originalEvent.touches ? event.originalEvent.touches[0] : event;
@@ -2148,16 +2148,16 @@
             this._setDropPosition(x, y);
         },
 
-		/**
-		 * Sets the target position, highlighting the appropriate area
-		 *
-		 * @param   {Number} x The x position in px
-		 * @param   {Number} y The y position in px
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Sets the target position, highlighting the appropriate area
+         *
+         * @param   {Number} x The x position in px
+         * @param   {Number} y The y position in px
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _setDropPosition: function (x, y) {
             this.element.css({ left: x, top: y });
             this._area = this._layoutManager._$getArea(x, y);
@@ -2168,43 +2168,43 @@
             }
         },
 
-		/**
-		 * Callback when the drag has finished. Determines the drop area
-		 * and adds the child to it
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Callback when the drag has finished. Determines the drop area
+         * and adds the child to it
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _onDrop: function () {
             this._layoutManager.dropTargetIndicator.hide();
 
-			/*
-			 * Valid drop area found
-			 */
+            /*
+             * Valid drop area found
+             */
             if (this._area !== null) {
                 this._area.contentItem._$onDrop(this._contentItem, this._area);
 
-				/**
-				 * No valid drop area available at present, but one has been found before.
-				 * Use it
-				 */
+                /**
+                 * No valid drop area available at present, but one has been found before.
+                 * Use it
+                 */
             } else if (this._lastValidArea !== null) {
                 this._lastValidArea.contentItem._$onDrop(this._contentItem, this._lastValidArea);
 
-				/**
-				 * No valid drop area found during the duration of the drag. Return
-				 * content item to its original position if a original parent is provided.
-				 * (Which is not the case if the drag had been initiated by createDragSource)
-				 */
+                /**
+                 * No valid drop area found during the duration of the drag. Return
+                 * content item to its original position if a original parent is provided.
+                 * (Which is not the case if the drag had been initiated by createDragSource)
+                 */
             } else if (this._originalParent) {
                 this._originalParent.addChild(this._contentItem);
 
-				/**
-				 * The drag didn't ultimately end up with adding the content item to
-				 * any container. In order to ensure clean up happens, destroy the
-				 * content item.
-				 */
+                /**
+                 * The drag didn't ultimately end up with adding the content item to
+                 * any container. In order to ensure clean up happens, destroy the
+                 * content item.
+                 */
             } else {
                 this._contentItem._$destroy();
             }
@@ -2215,18 +2215,18 @@
             this._layoutManager.emit('itemDropped', this._contentItem);
         },
 
-		/**
-		 * Removes the item from its original position within the tree
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Removes the item from its original position within the tree
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _updateTree: function () {
 
-			/**
-			 * parent is null if the drag had been initiated by a external drag source
-			 */
+            /**
+             * parent is null if the drag had been initiated by a external drag source
+             */
             if (this._contentItem.parent) {
                 this._contentItem.parent.removeChild(this._contentItem, true);
             }
@@ -2234,13 +2234,13 @@
             this._contentItem._$setParent(this);
         },
 
-		/**
-		 * Updates the Drag Proxie's dimensions
-		 *
-		 * @private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Updates the Drag Proxie's dimensions
+         *
+         * @private
+         *
+         * @returns {void}
+         */
         _setDimensions: function () {
             var dimensions = this._layoutManager.config.dimensions,
                 width = dimensions.dragProxyWidth,
@@ -2259,16 +2259,16 @@
         }
     });
 
-	/**
-	 * Allows for any DOM item to create a component on drag
-	 * start tobe dragged into the Layout
-	 *
-	 * @param {jQuery element} element
-	 * @param {Object} itemConfig the configuration for the contentItem that will be created
-	 * @param {LayoutManager} layoutManager
-	 *
-	 * @constructor
-	 */
+    /**
+     * Allows for any DOM item to create a component on drag
+     * start tobe dragged into the Layout
+     *
+     * @param {jQuery element} element
+     * @param {Object} itemConfig the configuration for the contentItem that will be created
+     * @param {LayoutManager} layoutManager
+     *
+     * @constructor
+     */
     lm.controls.DragSource = function (element, itemConfig, layoutManager) {
         this._element = element;
         this._itemConfig = itemConfig;
@@ -2280,11 +2280,11 @@
 
     lm.utils.copy(lm.controls.DragSource.prototype, {
 
-		/**
-		 * Called initially and after every drag
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Called initially and after every drag
+         *
+         * @returns {void}
+         */
         _createDragListener: function () {
             if (this._dragListener !== null) {
                 this._dragListener.destroy();
@@ -2306,14 +2306,14 @@
             }
         },
 
-		/**
-		 * Callback for the DragListener's dragStart event
-		 *
-		 * @param   {int} x the x position of the mouse on dragStart
-		 * @param   {int} y the x position of the mouse on dragStart
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Callback for the DragListener's dragStart event
+         *
+         * @param   {int} x the x position of the mouse on dragStart
+         * @param   {int} y the x position of the mouse on dragStart
+         *
+         * @returns {void}
+         */
         _onDragStart: function (x, y) {
             var itemConfig = this._itemConfig;
             if (lm.utils.isFunction(itemConfig)) {
@@ -2355,12 +2355,12 @@
             this.element.hide();
         }
     });
-	/**
-	 * This class represents a header above a Stack ContentItem.
-	 *
-	 * @param {lm.LayoutManager} layoutManager
-	 * @param {lm.item.AbstractContentItem} parent
-	 */
+    /**
+     * This class represents a header above a Stack ContentItem.
+     *
+     * @param {lm.LayoutManager} layoutManager
+     * @param {lm.item.AbstractContentItem} parent
+     */
     lm.controls.Header = function (layoutManager, parent) {
         lm.utils.EventEmitter.call(this);
 
@@ -2390,24 +2390,24 @@
         this._createControls();
     };
 
+    // '<ul class="lm_tabdropdown_list"></ul>',
     lm.controls.Header._template = [
         '<div class="lm_header">',
         '<ul class="lm_tabs"></ul>',
         '<ul class="lm_controls"></ul>',
-        '<ul class="lm_tabdropdown_list"></ul>',
         '</div>'
     ].join('');
 
     lm.utils.copy(lm.controls.Header.prototype, {
 
-		/**
-		 * Creates a new tab and associates it with a contentItem
-		 *
-		 * @param    {lm.item.AbstractContentItem} contentItem
-		 * @param    {Integer} index The position of the tab
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Creates a new tab and associates it with a contentItem
+         *
+         * @param    {lm.item.AbstractContentItem} contentItem
+         * @param    {Integer} index The position of the tab
+         *
+         * @returns {void}
+         */
         createTab: function (contentItem, index) {
             var tab, i;
 
@@ -2441,13 +2441,13 @@
             this._updateTabSizes();
         },
 
-		/**
-		 * Finds a tab based on the contentItem its associated with and removes it.
-		 *
-		 * @param    {lm.item.AbstractContentItem} contentItem
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Finds a tab based on the contentItem its associated with and removes it.
+         *
+         * @param    {lm.item.AbstractContentItem} contentItem
+         *
+         * @returns {void}
+         */
         removeTab: function (contentItem) {
             for (var i = 0; i < this.tabs.length; i++) {
                 if (this.tabs[i].contentItem === contentItem) {
@@ -2460,11 +2460,11 @@
             throw new Error('contentItem is not controlled by this header');
         },
 
-		/**
-		 * The programmatical equivalent of clicking a Tab.
-		 *
-		 * @param {lm.item.AbstractContentItem} contentItem
-		 */
+        /**
+         * The programmatical equivalent of clicking a Tab.
+         *
+         * @param {lm.item.AbstractContentItem} contentItem
+         */
         setActiveContentItem: function (contentItem) {
             var i, j, isActive, activeTab;
 
@@ -2478,10 +2478,10 @@
             }
 
             if (this.layoutManager.config.settings.reorderOnTabMenuClick) {
-				/**
-				 * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
-				 * This will make sure the most used tabs stay visible.
-				 */
+                /**
+                 * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
+                 * This will make sure the most used tabs stay visible.
+                 */
                 if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) {
                     activeTab = this.tabs[this.parent.config.activeItemIndex];
                     for (j = this.parent.config.activeItemIndex; j > 0; j--) {
@@ -2496,13 +2496,13 @@
             this.parent.emitBubblingEvent('stateChanged');
         },
 
-		/**
-		 * Programmatically operate with header position.
-		 *
-		 * @param {string} position one of ('top','left','right','bottom') to set or empty to get it.
-		 *
-		 * @returns {string} previous header position
-		 */
+        /**
+         * Programmatically operate with header position.
+         *
+         * @param {string} position one of ('top','left','right','bottom') to set or empty to get it.
+         *
+         * @returns {string} previous header position
+         */
         position: function (position) {
             var previous = this.parent._header.show;
             if (previous && !this.parent._side)
@@ -2514,14 +2514,14 @@
             return previous;
         },
 
-		/**
-		 * Programmatically set closability.
-		 *
-		 * @package private
-		 * @param {Boolean} isClosable Whether to enable/disable closability.
-		 *
-		 * @returns {Boolean} Whether the action was successful
-		 */
+        /**
+         * Programmatically set closability.
+         *
+         * @package private
+         * @param {Boolean} isClosable Whether to enable/disable closability.
+         *
+         * @returns {Boolean} Whether the action was successful
+         */
         _$setClosable: function (isClosable) {
             if (this.closeButton && this._isClosable()) {
                 this.closeButton.element[isClosable ? "show" : "hide"]();
@@ -2531,13 +2531,13 @@
             return false;
         },
 
-		/**
-		 * Destroys the entire header
-		 *
-		 * @package private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Destroys the entire header
+         *
+         * @package private
+         *
+         * @returns {void}
+         */
         _$destroy: function () {
             this.emit('destroy', this);
 
@@ -2548,20 +2548,20 @@
             this.element.remove();
         },
 
-		/**
-		 * get settings from header
-		 *
-		 * @returns {string} when exists
-		 */
+        /**
+         * get settings from header
+         *
+         * @returns {string} when exists
+         */
         _getHeaderSetting: function (name) {
             if (name in this.parent._header)
                 return this.parent._header[name];
         },
-		/**
-		 * Creates the popout, maximise and close buttons in the header's top right corner
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Creates the popout, maximise and close buttons in the header's top right corner
+         *
+         * @returns {void}
+         */
         _createControls: function () {
             var closeStack,
                 popout,
@@ -2573,26 +2573,26 @@
                 tabDropdownLabel,
                 showTabDropdown;
 
-			/**
-			 * Dropdown to show additional tabs.
-			 */
+            /**
+             * Dropdown to show additional tabs.
+             */
             showTabDropdown = lm.utils.fnBind(this._showAdditionalTabsDropdown, this);
             tabDropdownLabel = this.layoutManager.config.labels.tabDropdown;
-            this.tabDropdownButton = new lm.controls.HeaderButton(this, tabDropdownLabel, 'lm_tabdropdown', showTabDropdown);
-            this.tabDropdownButton.element.hide();
+            // this.tabDropdownButton = new lm.controls.HeaderButton(this, tabDropdownLabel, 'lm_tabdropdown', showTabDropdown);
+            // this.tabDropdownButton.element.hide();
 
-			/**
-			 * Popout control to launch component in new window.
-			 */
+            /**
+             * Popout control to launch component in new window.
+             */
             if (this._getHeaderSetting('popout')) {
                 popout = lm.utils.fnBind(this._onPopoutClick, this);
                 label = this._getHeaderSetting('popout');
                 new lm.controls.HeaderButton(this, label, 'lm_popout', popout);
             }
 
-			/**
-			 * Maximise control - set the component to the full size of the layout
-			 */
+            /**
+             * Maximise control - set the component to the full size of the layout
+             */
             if (this._getHeaderSetting('maximise')) {
                 maximise = lm.utils.fnBind(this.parent.toggleMaximise, this.parent);
                 maximiseLabel = this._getHeaderSetting('maximise');
@@ -2608,9 +2608,9 @@
                 });
             }
 
-			/**
-			 * Close button
-			 */
+            /**
+             * Close button
+             */
             if (this._isClosable()) {
                 closeStack = lm.utils.fnBind(this.parent.remove, this.parent);
                 label = this._getHeaderSetting('close');
@@ -2618,30 +2618,30 @@
             }
         },
 
-		/**
-		 * Shows drop down for additional tabs when there are too many to display.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Shows drop down for additional tabs when there are too many to display.
+         *
+         * @returns {void}
+         */
         _showAdditionalTabsDropdown: function () {
             this.tabDropdownContainer.show();
         },
 
-		/**
-		 * Hides drop down for additional tabs when there are too many to display.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Hides drop down for additional tabs when there are too many to display.
+         *
+         * @returns {void}
+         */
         _hideAdditionalTabsDropdown: function (e) {
             this.tabDropdownContainer.hide();
         },
 
-		/**
-		 * Checks whether the header is closable based on the parent config and
-		 * the global config.
-		 *
-		 * @returns {Boolean} Whether the header is closable.
-		 */
+        /**
+         * Checks whether the header is closable based on the parent config and
+         * the global config.
+         *
+         * @returns {Boolean} Whether the header is closable.
+         */
         _isClosable: function () {
             return this.parent.config.isClosable && this.layoutManager.config.settings.showCloseIcon;
         },
@@ -2655,32 +2655,29 @@
         },
 
 
-		/**
-		 * Invoked when the header's background is clicked (not it's tabs or controls)
-		 *
-		 * @param    {jQuery DOM event} event
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Invoked when the header's background is clicked (not it's tabs or controls)
+         *
+         * @param    {jQuery DOM event} event
+         *
+         * @returns {void}
+         */
         _onHeaderClick: function (event) {
             if (event.target === this.element[0]) {
                 this.parent.select();
             }
         },
 
-		/**
-		 * Pushes the tabs to the tab dropdown if the available space is not sufficient
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Pushes the tabs to the tab dropdown if the available space is not sufficient
+         *
+         * @returns {void}
+         */
         _updateTabSizes: function (showTabMenu) {
             if (this.tabs.length === 0) {
                 return;
             }
 
-            //Show the menu based on function argument
-            this.tabDropdownButton.element.toggle(showTabMenu === true);
-
             var size = function (val) {
                 return val ? 'width' : 'height';
             };
@@ -2835,14 +2832,14 @@
         }
     });
 
-	/**
-	 * Represents an individual tab within a Stack's header
-	 *
-	 * @param {lm.controls.Header} header
-	 * @param {lm.items.AbstractContentItem} contentItem
-	 *
-	 * @constructor
-	 */
+    /**
+     * Represents an individual tab within a Stack's header
+     *
+     * @param {lm.controls.Header} header
+     * @param {lm.items.AbstractContentItem} contentItem
+     *
+     * @constructor
+     */
     lm.controls.Tab = function (header, contentItem) {
         this.header = header;
         this.contentItem = contentItem;
@@ -2888,37 +2885,37 @@
         }
     };
 
-	/**
-	 * The tab's html template
-	 *
-	 * @type {String}
-	 */
+    /**
+     * The tab's html template
+     *
+     * @type {String}
+     */
     lm.controls.Tab._template = '<li class="lm_tab"><i class="lm_left"></i>' +
         '<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab"></div>' +
         '<i class="lm_right"></i></li>';
 
     lm.utils.copy(lm.controls.Tab.prototype, {
 
-		/**
-		 * Sets the tab's title to the provided string and sets
-		 * its title attribute to a pure text representation (without
-		 * html tags) of the same string.
-		 *
-		 * @public
-		 * @param {String} title can contain html
-		 */
+        /**
+         * Sets the tab's title to the provided string and sets
+         * its title attribute to a pure text representation (without
+         * html tags) of the same string.
+         *
+         * @public
+         * @param {String} title can contain html
+         */
         setTitle: function (title) {
             this.element.attr('title', lm.utils.stripTags(title));
             this.titleElement.html(title);
         },
 
-		/**
-		 * Sets this tab's active state. To programmatically
-		 * switch tabs, use header.setActiveContentItem( item ) instead.
-		 *
-		 * @public
-		 * @param {Boolean} isActive
-		 */
+        /**
+         * Sets this tab's active state. To programmatically
+         * switch tabs, use header.setActiveContentItem( item ) instead.
+         *
+         * @public
+         * @param {Boolean} isActive
+         */
         setActive: function (isActive) {
             if (isActive === this.isActive) {
                 return;
@@ -2932,12 +2929,12 @@
             }
         },
 
-		/**
-		 * Destroys the tab
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Destroys the tab
+         *
+         * @private
+         * @returns {void}
+         */
         _$destroy: function () {
             this._layoutManager.emit('tabDestroyed', this);
             this.element.off('mousedown touchstart', this._onTabClickFn);
@@ -2950,15 +2947,15 @@
             this.element.remove();
         },
 
-		/**
-		 * Callback for the DragListener
-		 *
-		 * @param   {Number} x The tabs absolute x position
-		 * @param   {Number} y The tabs absolute y position
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Callback for the DragListener
+         *
+         * @param   {Number} x The tabs absolute x position
+         * @param   {Number} y The tabs absolute y position
+         *
+         * @private
+         * @returns {void}
+         */
         _onDragStart: function (x, y) {
             if (this.contentItem.parent.isMaximised === true) {
                 this.contentItem.parent.toggleMaximise();
@@ -2973,14 +2970,14 @@
             );
         },
 
-		/**
-		 * Callback when the tab is clicked
-		 *
-		 * @param {jQuery DOM event} event
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Callback when the tab is clicked
+         *
+         * @param {jQuery DOM event} event
+         *
+         * @private
+         * @returns {void}
+         */
         _onTabClick: function (event) {
             // left mouse button or tap
             if (event.button === 0 || event.type === 'touchstart') {
@@ -2995,30 +2992,30 @@
             }
         },
 
-		/**
-		 * Callback when the tab's close button is
-		 * clicked
-		 *
-		 * @param   {jQuery DOM event} event
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Callback when the tab's close button is
+         * clicked
+         *
+         * @param   {jQuery DOM event} event
+         *
+         * @private
+         * @returns {void}
+         */
         _onCloseClick: function (event) {
             event.stopPropagation();
             this.header.parent.removeChild(this.contentItem);
         },
 
 
-		/**
-		 * Callback to capture tab close button mousedown
-		 * to prevent tab from activating.
-		 *
-		 * @param (jQuery DOM event) event
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Callback to capture tab close button mousedown
+         * to prevent tab from activating.
+         *
+         * @param (jQuery DOM event) event
+         *
+         * @private
+         * @returns {void}
+         */
         _onCloseMousedown: function (event) {
             event.stopPropagation();
         }
@@ -3040,9 +3037,9 @@
         },
 
         transitionElements: function (fromElement, toElement) {
-			/**
-			 * TODO - This is not quite as cool as expected. Review.
-			 */
+            /**
+             * TODO - This is not quite as cool as expected. Review.
+             */
             return;
             this._toElement = toElement;
             this._animationStartTime = lm.utils.now();
@@ -3096,27 +3093,27 @@
 
     lm.errors.ConfigurationError.prototype = new Error();
 
-	/**
-	 * This is the baseclass that all content items inherit from.
-	 * Most methods provide a subset of what the sub-classes do.
-	 *
-	 * It also provides a number of functions for tree traversal
-	 *
-	 * @param {lm.LayoutManager} layoutManager
-	 * @param {item node configuration} config
-	 * @param {lm.item} parent
-	 *
-	 * @event stateChanged
-	 * @event beforeItemDestroyed
-	 * @event itemDestroyed
-	 * @event itemCreated
-	 * @event componentCreated
-	 * @event rowCreated
-	 * @event columnCreated
-	 * @event stackCreated
-	 *
-	 * @constructor
-	 */
+    /**
+     * This is the baseclass that all content items inherit from.
+     * Most methods provide a subset of what the sub-classes do.
+     *
+     * It also provides a number of functions for tree traversal
+     *
+     * @param {lm.LayoutManager} layoutManager
+     * @param {item node configuration} config
+     * @param {lm.item} parent
+     *
+     * @event stateChanged
+     * @event beforeItemDestroyed
+     * @event itemDestroyed
+     * @event itemCreated
+     * @event componentCreated
+     * @event rowCreated
+     * @event columnCreated
+     * @event stackCreated
+     *
+     * @constructor
+     */
     lm.items.AbstractContentItem = function (layoutManager, config, parent) {
         lm.utils.EventEmitter.call(this);
 
@@ -3146,26 +3143,26 @@
 
     lm.utils.copy(lm.items.AbstractContentItem.prototype, {
 
-		/**
-		 * Set the size of the component and its children, called recursively
-		 *
-		 * @abstract
-		 * @returns void
-		 */
+        /**
+         * Set the size of the component and its children, called recursively
+         *
+         * @abstract
+         * @returns void
+         */
         setSize: function () {
             throw new Error('Abstract Method');
         },
 
-		/**
-		 * Calls a method recursively downwards on the tree
-		 *
-		 * @param   {String} functionName      the name of the function to be called
-		 * @param   {[Array]}functionArguments optional arguments that are passed to every function
-		 * @param   {[bool]} bottomUp          Call methods from bottom to top, defaults to false
-		 * @param   {[bool]} skipSelf          Don't invoke the method on the class that calls it, defaults to false
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Calls a method recursively downwards on the tree
+         *
+         * @param   {String} functionName      the name of the function to be called
+         * @param   {[Array]}functionArguments optional arguments that are passed to every function
+         * @param   {[bool]} bottomUp          Call methods from bottom to top, defaults to false
+         * @param   {[bool]} skipSelf          Don't invoke the method on the class that calls it, defaults to false
+         *
+         * @returns {void}
+         */
         callDownwards: function (functionName, functionArguments, bottomUp, skipSelf) {
             var i;
 
@@ -3180,53 +3177,53 @@
             }
         },
 
-		/**
-		 * Removes a child node (and its children) from the tree
-		 *
-		 * @param   {lm.items.ContentItem} contentItem
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Removes a child node (and its children) from the tree
+         *
+         * @param   {lm.items.ContentItem} contentItem
+         *
+         * @returns {void}
+         */
         removeChild: function (contentItem, keepChild) {
 
-			/*
-			 * Get the position of the item that's to be removed within all content items this node contains
-			 */
+            /*
+             * Get the position of the item that's to be removed within all content items this node contains
+             */
             var index = lm.utils.indexOf(contentItem, this.contentItems);
 
-			/*
-			 * Make sure the content item to be removed is actually a child of this item
-			 */
+            /*
+             * Make sure the content item to be removed is actually a child of this item
+             */
             if (index === -1) {
                 throw new Error('Can\'t remove child item. Unknown content item');
             }
 
-			/**
-			 * Call ._$destroy on the content item. This also calls ._$destroy on all its children
-			 */
+            /**
+             * Call ._$destroy on the content item. This also calls ._$destroy on all its children
+             */
             if (keepChild !== true) {
                 this.contentItems[index]._$destroy();
             }
 
-			/**
-			 * Remove the content item from this nodes array of children
-			 */
+            /**
+             * Remove the content item from this nodes array of children
+             */
             this.contentItems.splice(index, 1);
 
-			/**
-			 * Remove the item from the configuration
-			 */
+            /**
+             * Remove the item from the configuration
+             */
             this.config.content.splice(index, 1);
 
-			/**
-			 * If this node still contains other content items, adjust their size
-			 */
+            /**
+             * If this node still contains other content items, adjust their size
+             */
             if (this.contentItems.length > 0) {
                 this.callDownwards('setSize');
 
-				/**
-				 * If this was the last content item, remove this node as well
-				 */
+                /**
+                 * If this was the last content item, remove this node as well
+                 */
             } else if (!(this instanceof lm.items.Root) && this.config.isClosable === true) {
                 const stack = this;
                 const rowOrCol = stack.parent;
@@ -3244,14 +3241,14 @@
             }
         },
 
-		/**
-		 * Sets up the tree structure for the newly added child
-		 * The responsibility for the actual DOM manipulations lies
-		 * with the concrete item
-		 *
-		 * @param {lm.items.AbstractContentItem} contentItem
-		 * @param {[Int]} index If omitted item will be appended
-		 */
+        /**
+         * Sets up the tree structure for the newly added child
+         * The responsibility for the actual DOM manipulations lies
+         * with the concrete item
+         *
+         * @param {lm.items.AbstractContentItem} contentItem
+         * @param {[Int]} index If omitted item will be appended
+         */
         addChild: function (contentItem, index) {
             if (index === undefined) {
                 index = this.contentItems.length;
@@ -3271,15 +3268,15 @@
             }
         },
 
-		/**
-		 * Replaces oldChild with newChild. This used to use jQuery.replaceWith... which for
-		 * some reason removes all event listeners, so isn't really an option.
-		 *
-		 * @param   {lm.item.AbstractContentItem} oldChild
-		 * @param   {lm.item.AbstractContentItem} newChild
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Replaces oldChild with newChild. This used to use jQuery.replaceWith... which for
+         * some reason removes all event listeners, so isn't really an option.
+         *
+         * @param   {lm.item.AbstractContentItem} oldChild
+         * @param   {lm.item.AbstractContentItem} newChild
+         *
+         * @returns {void}
+         */
         replaceChild: function (oldChild, newChild, _$destroyOldChild) {
 
             newChild = this.layoutManager._$normalizeContentItem(newChild);
@@ -3293,23 +3290,23 @@
 
             parentNode.replaceChild(newChild.element[0], oldChild.element[0]);
 
-			/*
-			 * Optionally destroy the old content item
-			 */
+            /*
+             * Optionally destroy the old content item
+             */
             if (_$destroyOldChild === true) {
                 oldChild.parent = null;
                 oldChild._$destroy();
             }
 
-			/*
-			 * Wire the new contentItem into the tree
-			 */
+            /*
+             * Wire the new contentItem into the tree
+             */
             this.contentItems[index] = newChild;
             newChild.parent = this;
 
-			/*
-			 * Update tab reference
-			 */
+            /*
+             * Update tab reference
+             */
             if (this.isStack) {
                 this.header.tabs[index].contentItem = newChild;
             }
@@ -3322,33 +3319,33 @@
             this.callDownwards('setSize');
         },
 
-		/**
-		 * Convenience method.
-		 * Shorthand for this.parent.removeChild( this )
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Convenience method.
+         * Shorthand for this.parent.removeChild( this )
+         *
+         * @returns {void}
+         */
         remove: function () {
             this.parent.removeChild(this);
         },
 
-		/**
-		 * Removes the component from the layout and creates a new
-		 * browser window with the component and its children inside
-		 *
-		 * @returns {lm.controls.BrowserPopout}
-		 */
+        /**
+         * Removes the component from the layout and creates a new
+         * browser window with the component and its children inside
+         *
+         * @returns {lm.controls.BrowserPopout}
+         */
         popout: function () {
             var browserPopout = this.layoutManager.createPopout(this);
             this.emitBubblingEvent('stateChanged');
             return browserPopout;
         },
 
-		/**
-		 * Maximises the Item or minimises it if it is already maximised
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Maximises the Item or minimises it if it is already maximised
+         *
+         * @returns {void}
+         */
         toggleMaximise: function (e) {
             e && e.preventDefault();
             if (this.isMaximised === true) {
@@ -3361,11 +3358,11 @@
             this.emitBubblingEvent('stateChanged');
         },
 
-		/**
-		 * Selects the item if it is not already selected
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Selects the item if it is not already selected
+         *
+         * @returns {void}
+         */
         select: function () {
             if (this.layoutManager.selectedItem !== this) {
                 this.layoutManager.selectItem(this, true);
@@ -3373,11 +3370,11 @@
             }
         },
 
-		/**
-		 * De-selects the item if it is selected
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * De-selects the item if it is selected
+         *
+         * @returns {void}
+         */
         deselect: function () {
             if (this.layoutManager.selectedItem === this) {
                 this.layoutManager.selectedItem = null;
@@ -3385,28 +3382,28 @@
             }
         },
 
-		/**
-		 * Set this component's title
-		 *
-		 * @public
-		 * @param {String} title
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Set this component's title
+         *
+         * @public
+         * @param {String} title
+         *
+         * @returns {void}
+         */
         setTitle: function (title) {
             this.config.title = title;
             this.emit('titleChanged', title);
             this.emit('stateChanged');
         },
 
-		/**
-		 * Checks whether a provided id is present
-		 *
-		 * @public
-		 * @param   {String}  id
-		 *
-		 * @returns {Boolean} isPresent
-		 */
+        /**
+         * Checks whether a provided id is present
+         *
+         * @public
+         * @param   {String}  id
+         *
+         * @returns {Boolean} isPresent
+         */
         hasId: function (id) {
             if (!this.config.id) {
                 return false;
@@ -3417,15 +3414,15 @@
             }
         },
 
-		/**
-		 * Adds an id. Adds it as a string if the component doesn't
-		 * have an id yet or creates/uses an array
-		 *
-		 * @public
-		 * @param {String} id
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Adds an id. Adds it as a string if the component doesn't
+         * have an id yet or creates/uses an array
+         *
+         * @public
+         * @param {String} id
+         *
+         * @returns {void}
+         */
         addId: function (id) {
             if (this.hasId(id)) {
                 return;
@@ -3440,15 +3437,15 @@
             }
         },
 
-		/**
-		 * Removes an existing id. Throws an error
-		 * if the id is not present
-		 *
-		 * @public
-		 * @param   {String} id
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Removes an existing id. Throws an error
+         * if the id is not present
+         *
+         * @public
+         * @param   {String} id
+         *
+         * @returns {void}
+         */
         removeId: function (id) {
             if (!this.hasId(id)) {
                 throw new Error('Id not found');
@@ -3462,9 +3459,9 @@
             }
         },
 
-		/****************************************
-		 * SELECTOR
-		 ****************************************/
+        /****************************************
+         * SELECTOR
+         ****************************************/
         getItemsByFilter: function (filter) {
             var result = [],
                 next = function (contentItem) {
@@ -3508,9 +3505,9 @@
             return instances;
         },
 
-		/****************************************
-		 * PACKAGE PRIVATE
-		 ****************************************/
+        /****************************************
+         * PACKAGE PRIVATE
+         ****************************************/
         _$getItemsByProperty: function (key, value) {
             return this.getItemsByFilter(function (item) {
                 return item[key] === value;
@@ -3555,11 +3552,11 @@
             }
         },
 
-		/**
-		 * Destroys this item ands its children
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Destroys this item ands its children
+         *
+         * @returns {void}
+         */
         _$destroy: function () {
             this.emitBubblingEvent('beforeItemDestroyed');
             this.callDownwards('_$destroy', [], true, true);
@@ -3567,17 +3564,17 @@
             this.emitBubblingEvent('itemDestroyed');
         },
 
-		/**
-		 * Returns the area the component currently occupies in the format
-		 *
-		 * {
-		 *		x1: int
-		 *		xy: int
-		 *		y1: int
-		 *		y2: int
-		 *		contentItem: contentItem
-		 * }
-		 */
+        /**
+         * Returns the area the component currently occupies in the format
+         *
+         * {
+         *		x1: int
+         *		xy: int
+         *		y1: int
+         *		y2: int
+         *		contentItem: contentItem
+         * }
+         */
         _$getArea: function (element) {
             element = element || this.element;
 
@@ -3595,17 +3592,17 @@
             };
         },
 
-		/**
-		 * The tree of content items is created in two steps: First all content items are instantiated,
-		 * then init is called recursively from top to bottem. This is the basic init function,
-		 * it can be used, extended or overwritten by the content items
-		 *
-		 * Its behaviour depends on the content item
-		 *
-		 * @package private
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * The tree of content items is created in two steps: First all content items are instantiated,
+         * then init is called recursively from top to bottem. This is the basic init function,
+         * it can be used, extended or overwritten by the content items
+         *
+         * Its behaviour depends on the content item
+         *
+         * @package private
+         *
+         * @returns {void}
+         */
         _$init: function () {
             var i;
             this.setSize();
@@ -3619,26 +3616,26 @@
             this.emitBubblingEvent(this.type + 'Created');
         },
 
-		/**
-		 * Emit an event that bubbles up the item tree.
-		 *
-		 * @param   {String} name The name of the event
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Emit an event that bubbles up the item tree.
+         *
+         * @param   {String} name The name of the event
+         *
+         * @returns {void}
+         */
         emitBubblingEvent: function (name) {
             var event = new lm.utils.BubblingEvent(name, this);
             this.emit(name, event);
         },
 
-		/**
-		 * Private method, creates all content items for this node at initialisation time
-		 * PLEASE NOTE, please see addChild for adding contentItems add runtime
-		 * @private
-		 * @param   {configuration item node} config
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Private method, creates all content items for this node at initialisation time
+         * PLEASE NOTE, please see addChild for adding contentItems add runtime
+         * @private
+         * @param   {configuration item node} config
+         *
+         * @returns {void}
+         */
         _createContentItems: function (config) {
             var oContentItem, i;
 
@@ -3652,13 +3649,13 @@
             }
         },
 
-		/**
-		 * Extends an item configuration node with default settings
-		 * @private
-		 * @param   {configuration item node} config
-		 *
-		 * @returns {configuration item node} extended config
-		 */
+        /**
+         * Extends an item configuration node with default settings
+         * @private
+         * @param   {configuration item node} config
+         *
+         * @returns {configuration item node} extended config
+         */
         _extendItemNode: function (config) {
 
             for (var key in lm.config.itemDefaultConfig) {
@@ -3670,26 +3667,26 @@
             return config;
         },
 
-		/**
-		 * Called for every event on the item tree. Decides whether the event is a bubbling
-		 * event and propagates it to its parent
-		 *
-		 * @param    {String} name the name of the event
-		 * @param   {lm.utils.BubblingEvent} event
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Called for every event on the item tree. Decides whether the event is a bubbling
+         * event and propagates it to its parent
+         *
+         * @param    {String} name the name of the event
+         * @param   {lm.utils.BubblingEvent} event
+         *
+         * @returns {void}
+         */
         _propagateEvent: function (name, event) {
             if (event instanceof lm.utils.BubblingEvent &&
                 event.isPropagationStopped === false &&
                 this.isInitialised === true) {
 
-				/**
-				 * In some cases (e.g. if an element is created from a DragSource) it
-				 * doesn't have a parent and is not below root. If that's the case
-				 * propagate the bubbling event from the top level of the substree directly
-				 * to the layoutManager
-				 */
+                /**
+                 * In some cases (e.g. if an element is created from a DragSource) it
+                 * doesn't have a parent and is not below root. If that's the case
+                 * propagate the bubbling event from the top level of the substree directly
+                 * to the layoutManager
+                 */
                 if (this.isRoot === false && this.parent) {
                     this.parent.emit.apply(this.parent, Array.prototype.slice.call(arguments, 0));
                 } else {
@@ -3698,16 +3695,16 @@
             }
         },
 
-		/**
-		 * All raw events bubble up to the root element. Some events that
-		 * are propagated to - and emitted by - the layoutManager however are
-		 * only string-based, batched and sanitized to make them more usable
-		 *
-		 * @param {String} name the name of the event
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * All raw events bubble up to the root element. Some events that
+         * are propagated to - and emitted by - the layoutManager however are
+         * only string-based, batched and sanitized to make them more usable
+         *
+         * @param {String} name the name of the event
+         *
+         * @private
+         * @returns {void}
+         */
         _scheduleEventPropagationToLayoutManager: function (name, event) {
             if (lm.utils.indexOf(name, this._throttledEvents) === -1) {
                 this.layoutManager.emit(name, event.origin);
@@ -3720,25 +3717,25 @@
 
         },
 
-		/**
-		 * Callback for events scheduled by _scheduleEventPropagationToLayoutManager
-		 *
-		 * @param {String} name the name of the event
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Callback for events scheduled by _scheduleEventPropagationToLayoutManager
+         *
+         * @param {String} name the name of the event
+         *
+         * @private
+         * @returns {void}
+         */
         _propagateEventToLayoutManager: function (name, event) {
             this._pendingEventPropagations[name] = false;
             this.layoutManager.emit(name, event);
         }
     });
 
-	/**
-	 * @param {[type]} layoutManager [description]
-	 * @param {[type]} config      [description]
-	 * @param {[type]} parent        [description]
-	 */
+    /**
+     * @param {[type]} layoutManager [description]
+     * @param {[type]} config      [description]
+     * @param {[type]} parent        [description]
+     */
     lm.items.Component = function (layoutManager, config, parent) {
         lm.items.AbstractContentItem.call(this, layoutManager, config, parent);
 
@@ -3798,11 +3795,11 @@
             lm.items.AbstractContentItem.prototype._$destroy.call(this);
         },
 
-		/**
-		 * Dragging onto a component directly is not an option
-		 *
-		 * @returns null
-		 */
+        /**
+         * Dragging onto a component directly is not an option
+         *
+         * @returns null
+         */
         _$getArea: function () {
             return null;
         }
@@ -3841,9 +3838,9 @@
             this.element.width(width);
             this.element.height(height);
 
-			/*
-			 * Root can be empty
-			 */
+            /*
+             * Root can be empty
+             */
             if (this.contentItems[0]) {
                 this.contentItems[0].element.width(width);
                 this.contentItems[0].element.height(height);
@@ -3917,18 +3914,18 @@
 
     lm.utils.copy(lm.items.RowOrColumn.prototype, {
 
-		/**
-		 * Add a new contentItem to the Row or Column
-		 *
-		 * @param {lm.item.AbstractContentItem} contentItem
-		 * @param {[int]} index The position of the new item within the Row or Column.
-		 *                      If no index is provided the item will be added to the end
-		 * @param {[bool]} _$suspendResize If true the items won't be resized. This will leave the item in
-		 *                                 an inconsistent state and is only intended to be used if multiple
-		 *                                 children need to be added in one go and resize is called afterwards
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Add a new contentItem to the Row or Column
+         *
+         * @param {lm.item.AbstractContentItem} contentItem
+         * @param {[int]} index The position of the new item within the Row or Column.
+         *                      If no index is provided the item will be added to the end
+         * @param {[bool]} _$suspendResize If true the items won't be resized. This will leave the item in
+         *                                 an inconsistent state and is only intended to be used if multiple
+         *                                 children need to be added in one go and resize is called afterwards
+         *
+         * @returns {void}
+         */
         addChild: function (contentItem, index, _$suspendResize) {
 
             var newItemSize, itemSize, i, splitterElement;
@@ -3986,14 +3983,14 @@
 
         },
 
-		/**
-		 * Removes a child of this element
-		 *
-		 * @param   {lm.items.AbstractContentItem} contentItem
-		 * @param   {boolean} keepChild   If true the child will be removed, but not destroyed
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Removes a child of this element
+         *
+         * @param   {lm.items.AbstractContentItem} contentItem
+         * @param   {boolean} keepChild   If true the child will be removed, but not destroyed
+         *
+         * @returns {void}
+         */
         removeChild: function (contentItem, keepChild) {
             var removedItemSize = contentItem.config[this._dimension],
                 index = lm.utils.indexOf(contentItem, this.contentItems),
@@ -4005,10 +4002,10 @@
                 throw new Error('Can\'t remove child. ContentItem is not child of this Row or Column');
             }
 
-			/**
-			 * Remove the splitter before the item or after if the item happens
-			 * to be the first in the row/column
-			 */
+            /**
+             * Remove the splitter before the item or after if the item happens
+             * to be the first in the row/column
+             */
             if (this._splitter[splitterIndex]) {
                 this._splitter[splitterIndex]._$destroy();
                 this._splitter.splice(splitterIndex, 1);
@@ -4019,9 +4016,9 @@
                 if (this.contentItems[i].config.fixed)
                     fixedItemSize += this.contentItems[i].config[this._dimension];
             }
-			/**
-			 * Allocate the space that the removed item occupied to the remaining items
-			 */
+            /**
+             * Allocate the space that the removed item occupied to the remaining items
+             */
             for (i = 0; i < this.contentItems.length; i++) {
                 if (this.contentItems[i].config.fixed)
                     ;
@@ -4044,14 +4041,14 @@
             }
         },
 
-		/**
-		 * Replaces a child of this Row or Column with another contentItem
-		 *
-		 * @param   {lm.items.AbstractContentItem} oldChild
-		 * @param   {lm.items.AbstractContentItem} newChild
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Replaces a child of this Row or Column with another contentItem
+         *
+         * @param   {lm.items.AbstractContentItem} oldChild
+         * @param   {lm.items.AbstractContentItem} newChild
+         *
+         * @returns {void}
+         */
         replaceChild: function (oldChild, newChild) {
             var size = oldChild.config[this._dimension];
             lm.items.AbstractContentItem.prototype.replaceChild.call(this, oldChild, newChild);
@@ -4060,11 +4057,11 @@
             this.emitBubblingEvent('stateChanged');
         },
 
-		/**
-		 * Called whenever the dimensions of this item or one of its parents change
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Called whenever the dimensions of this item or one of its parents change
+         *
+         * @returns {void}
+         */
         setSize: function () {
             if (this.contentItems.length > 0) {
                 this._calculateRelativeSizes();
@@ -4074,15 +4071,15 @@
             this.emit('resize');
         },
 
-		/**
-		 * Invoked recursively by the layout manager. AbstractContentItem.init appends
-		 * the contentItem's DOM elements to the container, RowOrColumn init adds splitters
-		 * in between them
-		 *
-		 * @package private
-		 * @override AbstractContentItem._$init
-		 * @returns {void}
-		 */
+        /**
+         * Invoked recursively by the layout manager. AbstractContentItem.init appends
+         * the contentItem's DOM elements to the container, RowOrColumn init adds splitters
+         * in between them
+         *
+         * @package private
+         * @override AbstractContentItem._$init
+         * @returns {void}
+         */
         _$init: function () {
             if (this.isInitialised === true) return;
 
@@ -4095,15 +4092,15 @@
             }
         },
 
-		/**
-		 * Turns the relative sizes calculated by _calculateRelativeSizes into
-		 * absolute pixel values and applies them to the children's DOM elements
-		 *
-		 * Assigns additional pixels to counteract Math.floor
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Turns the relative sizes calculated by _calculateRelativeSizes into
+         * absolute pixel values and applies them to the children's DOM elements
+         *
+         * Assigns additional pixels to counteract Math.floor
+         *
+         * @private
+         * @returns {void}
+         */
         _setAbsoluteSizes: function () {
             var i,
                 sizeData = this._calculateAbsoluteSizes();
@@ -4123,10 +4120,10 @@
             }
         },
 
-		/**
-		 * Calculates the absolute sizes of all of the children of this Item.
-		 * @returns {object} - Set with absolute sizes and additional pixels.
-		 */
+        /**
+         * Calculates the absolute sizes of all of the children of this Item.
+         * @returns {object} - Set with absolute sizes and additional pixels.
+         */
         _calculateAbsoluteSizes: function () {
             var i,
                 totalSplitterSize = (this.contentItems.length - 1) * this._splitterSize,
@@ -4164,27 +4161,27 @@
             };
         },
 
-		/**
-		 * Calculates the relative sizes of all children of this Item. The logic
-		 * is as follows:
-		 *
-		 * - Add up the total size of all items that have a configured size
-		 *
-		 * - If the total == 100 (check for floating point errors)
-		 *        Excellent, job done
-		 *
-		 * - If the total is > 100,
-		 *        set the size of items without set dimensions to 1/3 and add this to the total
-		 *        set the size off all items so that the total is hundred relative to their original size
-		 *
-		 * - If the total is < 100
-		 *        If there are items without set dimensions, distribute the remainder to 100 evenly between them
-		 *        If there are no items without set dimensions, increase all items sizes relative to
-		 *        their original size so that they add up to 100
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Calculates the relative sizes of all children of this Item. The logic
+         * is as follows:
+         *
+         * - Add up the total size of all items that have a configured size
+         *
+         * - If the total == 100 (check for floating point errors)
+         *        Excellent, job done
+         *
+         * - If the total is > 100,
+         *        set the size of items without set dimensions to 1/3 and add this to the total
+         *        set the size off all items so that the total is hundred relative to their original size
+         *
+         * - If the total is < 100
+         *        If there are items without set dimensions, distribute the remainder to 100 evenly between them
+         *        If there are no items without set dimensions, increase all items sizes relative to
+         *        their original size so that they add up to 100
+         *
+         * @private
+         * @returns {void}
+         */
         _calculateRelativeSizes: function () {
 
             var i,
@@ -4200,17 +4197,17 @@
                 }
             }
 
-			/**
-			 * Everything adds up to hundred, all good :-)
-			 */
+            /**
+             * Everything adds up to hundred, all good :-)
+             */
             if (Math.round(total) === 100) {
                 this._respectMinItemWidth();
                 return;
             }
 
-			/**
-			 * Allocate the remaining size to the items without a set dimension
-			 */
+            /**
+             * Allocate the remaining size to the items without a set dimension
+             */
             if (Math.round(total) < 100 && itemsWithoutSetDimension.length > 0) {
                 for (i = 0; i < itemsWithoutSetDimension.length; i++) {
                     itemsWithoutSetDimension[i].config[dimension] = (100 - total) / itemsWithoutSetDimension.length;
@@ -4219,12 +4216,12 @@
                 return;
             }
 
-			/**
-			 * If the total is > 100, but there are also items without a set dimension left, assing 50
-			 * as their dimension and add it to the total
-			 *
-			 * This will be reset in the next step
-			 */
+            /**
+             * If the total is > 100, but there are also items without a set dimension left, assing 50
+             * as their dimension and add it to the total
+             *
+             * This will be reset in the next step
+             */
             if (Math.round(total) > 100) {
                 for (i = 0; i < itemsWithoutSetDimension.length; i++) {
                     itemsWithoutSetDimension[i].config[dimension] = 50;
@@ -4232,9 +4229,9 @@
                 }
             }
 
-			/**
-			 * Set every items size relative to 100 relative to its size to total
-			 */
+            /**
+             * Set every items size relative to 100 relative to its size to total
+             */
             for (i = 0; i < this.contentItems.length; i++) {
                 this.contentItems[i].config[dimension] = (this.contentItems[i].config[dimension] / total) * 100;
             }
@@ -4242,10 +4239,10 @@
             this._respectMinItemWidth();
         },
 
-		/**
-		 * Adjusts the column widths to respect the dimensions minItemWidth if set.
-		 * @returns {}
-		 */
+        /**
+         * Adjusts the column widths to respect the dimensions minItemWidth if set.
+         * @returns {}
+         */
         _respectMinItemWidth: function () {
             var minItemWidth = this.layoutManager.config.dimensions ? (this.layoutManager.config.dimensions.minItemWidth || 0) : 0,
                 sizeData = null,
@@ -4266,9 +4263,9 @@
 
             sizeData = this._calculateAbsoluteSizes();
 
-			/**
-			 * Figure out how much we are under the min item size total and how much room we have to use.
-			 */
+            /**
+             * Figure out how much we are under the min item size total and how much room we have to use.
+             */
             for (var i = 0; i < this.contentItems.length; i++) {
 
                 contentItem = this.contentItems[i];
@@ -4288,16 +4285,16 @@
                 allEntries.push(entry);
             }
 
-			/**
-			 * If there is nothing under min, or there is not enough over to make up the difference, do nothing.
-			 */
+            /**
+             * If there is nothing under min, or there is not enough over to make up the difference, do nothing.
+             */
             if (totalUnderMin === 0 || totalUnderMin > totalOverMin) {
                 return;
             }
 
-			/**
-			 * Evenly reduce all columns that are over the min item width to make up the difference.
-			 */
+            /**
+             * Evenly reduce all columns that are over the min item width to make up the difference.
+             */
             reducePercent = totalUnderMin / totalOverMin;
             remainingWidth = totalUnderMin;
             for (i = 0; i < entriesOverMin.length; i++) {
@@ -4307,31 +4304,31 @@
                 entry.width -= reducedWidth;
             }
 
-			/**
-			 * Take anything remaining from the last item.
-			 */
+            /**
+             * Take anything remaining from the last item.
+             */
             if (remainingWidth !== 0) {
                 allEntries[allEntries.length - 1].width -= remainingWidth;
             }
 
-			/**
-			 * Set every items size relative to 100 relative to its size to total
-			 */
+            /**
+             * Set every items size relative to 100 relative to its size to total
+             */
             for (i = 0; i < this.contentItems.length; i++) {
                 this.contentItems[i].config.width = (allEntries[i].width / sizeData.totalWidth) * 100;
             }
         },
 
-		/**
-		 * Instantiates a new lm.controls.Splitter, binds events to it and adds
-		 * it to the array of splitters at the position specified as the index argument
-		 *
-		 * What it doesn't do though is append the splitter to the DOM
-		 *
-		 * @param   {Int} index The position of the splitter
-		 *
-		 * @returns {lm.controls.Splitter}
-		 */
+        /**
+         * Instantiates a new lm.controls.Splitter, binds events to it and adds
+         * it to the array of splitters at the position specified as the index argument
+         *
+         * What it doesn't do though is append the splitter to the DOM
+         *
+         * @param   {Int} index The position of the splitter
+         *
+         * @returns {lm.controls.Splitter}
+         */
         _createSplitter: function (index) {
             var splitter;
             splitter = new lm.controls.Splitter(this._isColumn, this._splitterSize, this._splitterGrabSize);
@@ -4342,16 +4339,16 @@
             return splitter;
         },
 
-		/**
-		 * Locates the instance of lm.controls.Splitter in the array of
-		 * registered splitters and returns a map containing the contentItem
-		 * before and after the splitters, both of which are affected if the
-		 * splitter is moved
-		 *
-		 * @param   {lm.controls.Splitter} splitter
-		 *
-		 * @returns {Object} A map of contentItems that the splitter affects
-		 */
+        /**
+         * Locates the instance of lm.controls.Splitter in the array of
+         * registered splitters and returns a map containing the contentItem
+         * before and after the splitters, both of which are affected if the
+         * splitter is moved
+         *
+         * @param   {lm.controls.Splitter} splitter
+         *
+         * @returns {Object} A map of contentItems that the splitter affects
+         */
         _getItemsForSplitter: function (splitter) {
             var index = lm.utils.indexOf(splitter, this._splitter);
 
@@ -4361,11 +4358,11 @@
             };
         },
 
-		/**
-		 * Gets the minimum dimensions for the given item configuration array
-		 * @param item
-		 * @private
-		 */
+        /**
+         * Gets the minimum dimensions for the given item configuration array
+         * @param item
+         * @private
+         */
         _getMinimumDimensions: function (arr) {
             var minWidth = 0, minHeight = 0;
 
@@ -4377,14 +4374,14 @@
             return { horizontal: minWidth, vertical: minHeight };
         },
 
-		/**
-		 * Invoked when a splitter's dragListener fires dragStart. Calculates the splitters
-		 * movement area once (so that it doesn't need calculating on every mousemove event)
-		 *
-		 * @param   {lm.controls.Splitter} splitter
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Invoked when a splitter's dragListener fires dragStart. Calculates the splitters
+         * movement area once (so that it doesn't need calculating on every mousemove event)
+         *
+         * @param   {lm.controls.Splitter} splitter
+         *
+         * @returns {void}
+         */
         _onSplitterDragStart: function (splitter) {
             var items = this._getItemsForSplitter(splitter),
                 minSize = this.layoutManager.config.dimensions[this._isColumn ? 'minItemHeight' : 'minItemWidth'];
@@ -4400,16 +4397,16 @@
             this._splitterMaxPosition = items.after.element[this._dimension]() - (afterMinSize || minSize);
         },
 
-		/**
-		 * Invoked when a splitter's DragListener fires drag. Updates the splitters DOM position,
-		 * but not the sizes of the elements the splitter controls in order to minimize resize events
-		 *
-		 * @param   {lm.controls.Splitter} splitter
-		 * @param   {Int} offsetX  Relative pixel values to the splitters original position. Can be negative
-		 * @param   {Int} offsetY  Relative pixel values to the splitters original position. Can be negative
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Invoked when a splitter's DragListener fires drag. Updates the splitters DOM position,
+         * but not the sizes of the elements the splitter controls in order to minimize resize events
+         *
+         * @param   {lm.controls.Splitter} splitter
+         * @param   {Int} offsetX  Relative pixel values to the splitters original position. Can be negative
+         * @param   {Int} offsetY  Relative pixel values to the splitters original position. Can be negative
+         *
+         * @returns {void}
+         */
         _onSplitterDrag: function (splitter, offsetX, offsetY) {
             var offset = this._isColumn ? offsetY : offsetX;
 
@@ -4419,15 +4416,15 @@
             }
         },
 
-		/**
-		 * Invoked when a splitter's DragListener fires dragStop. Resets the splitters DOM position,
-		 * and applies the new sizes to the elements before and after the splitter and their children
-		 * on the next animation frame
-		 *
-		 * @param   {lm.controls.Splitter} splitter
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Invoked when a splitter's DragListener fires dragStop. Resets the splitters DOM position,
+         * and applies the new sizes to the elements before and after the splitter and their children
+         * on the next animation frame
+         *
+         * @param   {lm.controls.Splitter} splitter
+         *
+         * @returns {void}
+         */
         _onSplitterDragStop: function (splitter) {
 
             var items = this._getItemsForSplitter(splitter),
@@ -4575,13 +4572,13 @@
             this.emitBubblingEvent('stateChanged');
         },
 
-		/**
-		 * Validates that the stack is still closable or not. If a stack is able
-		 * to close, but has a non closable component added to it, the stack is no
-		 * longer closable until all components are closable.
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Validates that the stack is still closable or not. If a stack is able
+         * to close, but has a non closable component added to it, the stack is no
+         * longer closable until all components are closable.
+         *
+         * @returns {void}
+         */
         _$validateClosability: function () {
             var contentItem,
                 isClosable,
@@ -4607,51 +4604,51 @@
         },
 
 
-		/**
-		 * Ok, this one is going to be the tricky one: The user has dropped {contentItem} onto this stack.
-		 *
-		 * It was dropped on either the stacks header or the top, right, bottom or left bit of the content area
-		 * (which one of those is stored in this._dropSegment). Now, if the user has dropped on the header the case
-		 * is relatively clear: We add the item to the existing stack... job done (might be good to have
-		 * tab reordering at some point, but lets not sweat it right now)
-		 *
-		 * If the item was dropped on the content part things are a bit more complicated. If it was dropped on either the
-		 * top or bottom region we need to create a new column and place the items accordingly.
-		 * Unless, of course if the stack is already within a column... in which case we want
-		 * to add the newly created item to the existing column...
-		 * either prepend or append it, depending on wether its top or bottom.
-		 *
-		 * Same thing for rows and left / right drop segments... so in total there are 9 things that can potentially happen
-		 * (left, top, right, bottom) * is child of the right parent (row, column) + header drop
-		 *
-		 * @param    {lm.item} contentItem
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Ok, this one is going to be the tricky one: The user has dropped {contentItem} onto this stack.
+         *
+         * It was dropped on either the stacks header or the top, right, bottom or left bit of the content area
+         * (which one of those is stored in this._dropSegment). Now, if the user has dropped on the header the case
+         * is relatively clear: We add the item to the existing stack... job done (might be good to have
+         * tab reordering at some point, but lets not sweat it right now)
+         *
+         * If the item was dropped on the content part things are a bit more complicated. If it was dropped on either the
+         * top or bottom region we need to create a new column and place the items accordingly.
+         * Unless, of course if the stack is already within a column... in which case we want
+         * to add the newly created item to the existing column...
+         * either prepend or append it, depending on wether its top or bottom.
+         *
+         * Same thing for rows and left / right drop segments... so in total there are 9 things that can potentially happen
+         * (left, top, right, bottom) * is child of the right parent (row, column) + header drop
+         *
+         * @param    {lm.item} contentItem
+         *
+         * @returns {void}
+         */
         _$onDrop: function (contentItem) {
 
-			/*
-			 * The item was dropped on the header area. Just add it as a child of this stack and
-			 * get the hell out of this logic
-			 */
+            /*
+             * The item was dropped on the header area. Just add it as a child of this stack and
+             * get the hell out of this logic
+             */
             if (this._dropSegment === 'header') {
                 this._resetHeaderDropZone();
                 this.addChild(contentItem, this._dropIndex);
                 return;
             }
 
-			/*
-			 * The stack is empty. Let's just add the element.
-			 */
+            /*
+             * The stack is empty. Let's just add the element.
+             */
             if (this._dropSegment === 'body') {
                 this.addChild(contentItem);
                 return;
             }
 
-			/*
-			 * The item was dropped on the top-, left-, bottom- or right- part of the content. Let's
-			 * aggregate some conditions to make the if statements later on more readable
-			 */
+            /*
+             * The item was dropped on the top-, left-, bottom- or right- part of the content. Let's
+             * aggregate some conditions to make the if statements later on more readable
+             */
             var isVertical = this._dropSegment === 'top' || this._dropSegment === 'bottom',
                 isHorizontal = this._dropSegment === 'left' || this._dropSegment === 'right',
                 insertBefore = this._dropSegment === 'top' || this._dropSegment === 'left',
@@ -4662,9 +4659,9 @@
                 stack,
                 rowOrColumn;
 
-			/*
-			 * The content item can be either a component or a stack. If it is a component, wrap it into a stack
-			 */
+            /*
+             * The content item can be either a component or a stack. If it is a component, wrap it into a stack
+             */
             if (contentItem.isComponent) {
                 stack = this.layoutManager.createContentItem({
                     type: 'stack',
@@ -4675,20 +4672,20 @@
                 contentItem = stack;
             }
 
-			/*
-			 * If the item is dropped on top or bottom of a column or left and right of a row, it's already
-			 * layd out in the correct way. Just add it as a child
-			 */
+            /*
+             * If the item is dropped on top or bottom of a column or left and right of a row, it's already
+             * layd out in the correct way. Just add it as a child
+             */
             if (hasCorrectParent) {
                 index = lm.utils.indexOf(this, this.parent.contentItems);
                 this.parent.addChild(contentItem, insertBefore ? index : index + 1, true);
                 this.config[dimension] *= 0.5;
                 contentItem.config[dimension] = this.config[dimension];
                 this.parent.callDownwards('setSize');
-				/*
-				 * This handles items that are dropped on top or bottom of a row or left / right of a column. We need
-				 * to create the appropriate contentItem for them to live in
-				 */
+                /*
+                 * This handles items that are dropped on top or bottom of a row or left / right of a column. We need
+                 * to create the appropriate contentItem for them to live in
+                 */
             } else {
                 type = isVertical ? 'column' : 'row';
                 rowOrColumn = this.layoutManager.createContentItem({ type: type }, this);
@@ -4703,15 +4700,15 @@
             }
         },
 
-		/**
-		 * If the user hovers above the header part of the stack, indicate drop positions for tabs.
-		 * otherwise indicate which segment of the body the dragged item would be dropped on
-		 *
-		 * @param    {Int} x Absolute Screen X
-		 * @param    {Int} y Absolute Screen Y
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * If the user hovers above the header part of the stack, indicate drop positions for tabs.
+         * otherwise indicate which segment of the body the dragged item would be dropped on
+         *
+         * @param    {Int} x Absolute Screen X
+         * @param    {Int} y Absolute Screen Y
+         *
+         * @returns {void}
+         */
         _$highlightDropZone: function (x, y) {
             var segment, area;
 
@@ -4761,17 +4758,17 @@
                 }
             };
 
-			/**
-			 * If this Stack is a parent to rows, columns or other stacks only its
-			 * header is a valid dropzone.
-			 */
+            /**
+             * If this Stack is a parent to rows, columns or other stacks only its
+             * header is a valid dropzone.
+             */
             if (this._activeContentItem && this._activeContentItem.isComponent === false) {
                 return headerArea;
             }
 
-			/**
-			 * Highlight the entire body if the stack is empty
-			 */
+            /**
+             * Highlight the entire body if the stack is empty
+             */
             if (this.contentItems.length === 0) {
 
                 this._contentAreaDimensions.body = {
@@ -4971,13 +4968,13 @@
     lm.utils.BubblingEvent.prototype.stopPropagation = function () {
         this.isPropagationStopped = true;
     };
-	/**
-	 * Minifies and unminifies configs by replacing frequent keys
-	 * and values with one letter substitutes. Config options must
-	 * retain array position/index, add new options at the end.
-	 *
-	 * @constructor
-	 */
+    /**
+     * Minifies and unminifies configs by replacing frequent keys
+     * and values with one letter substitutes. Config options must
+     * retain array position/index, add new options at the end.
+     *
+     * @constructor
+     */
     lm.utils.ConfigMinifier = function () {
         this._keys = [
             'settings',
@@ -5037,154 +5034,154 @@
 
     lm.utils.copy(lm.utils.ConfigMinifier.prototype, {
 
-		/**
-		 * Takes a GoldenLayout configuration object and
-		 * replaces its keys and values recursively with
-		 * one letter counterparts
-		 *
-		 * @param   {Object} config A GoldenLayout config object
-		 *
-		 * @returns {Object} minified config
-		 */
+        /**
+         * Takes a GoldenLayout configuration object and
+         * replaces its keys and values recursively with
+         * one letter counterparts
+         *
+         * @param   {Object} config A GoldenLayout config object
+         *
+         * @returns {Object} minified config
+         */
         minifyConfig: function (config) {
             var min = {};
             this._nextLevel(config, min, '_min');
             return min;
         },
 
-		/**
-		 * Takes a configuration Object that was previously minified
-		 * using minifyConfig and returns its original version
-		 *
-		 * @param   {Object} minifiedConfig
-		 *
-		 * @returns {Object} the original configuration
-		 */
+        /**
+         * Takes a configuration Object that was previously minified
+         * using minifyConfig and returns its original version
+         *
+         * @param   {Object} minifiedConfig
+         *
+         * @returns {Object} the original configuration
+         */
         unminifyConfig: function (minifiedConfig) {
             var orig = {};
             this._nextLevel(minifiedConfig, orig, '_max');
             return orig;
         },
 
-		/**
-		 * Recursive function, called for every level of the config structure
-		 *
-		 * @param   {Array|Object} orig
-		 * @param   {Array|Object} min
-		 * @param    {String} translationFn
-		 *
-		 * @returns {void}
-		 */
+        /**
+         * Recursive function, called for every level of the config structure
+         *
+         * @param   {Array|Object} orig
+         * @param   {Array|Object} min
+         * @param    {String} translationFn
+         *
+         * @returns {void}
+         */
         _nextLevel: function (from, to, translationFn) {
             var key, minKey;
 
             for (key in from) {
 
-				/**
-				 * For in returns array indices as keys, so let's cast them to numbers
-				 */
+                /**
+                 * For in returns array indices as keys, so let's cast them to numbers
+                 */
                 if (from instanceof Array) key = parseInt(key, 10);
 
-				/**
-				 * In case something has extended Object prototypes
-				 */
+                /**
+                 * In case something has extended Object prototypes
+                 */
                 if (!from.hasOwnProperty(key)) continue;
 
-				/**
-				 * Translate the key to a one letter substitute
-				 */
+                /**
+                 * Translate the key to a one letter substitute
+                 */
                 minKey = this[translationFn](key, this._keys);
 
-				/**
-				 * For Arrays and Objects, create a new Array/Object
-				 * on the minified object and recurse into it
-				 */
+                /**
+                 * For Arrays and Objects, create a new Array/Object
+                 * on the minified object and recurse into it
+                 */
                 if (typeof from[key] === 'object') {
                     to[minKey] = from[key] instanceof Array ? [] : {};
                     this._nextLevel(from[key], to[minKey], translationFn);
 
-					/**
-					 * For primitive values (Strings, Numbers, Boolean etc.)
-					 * minify the value
-					 */
+                    /**
+                     * For primitive values (Strings, Numbers, Boolean etc.)
+                     * minify the value
+                     */
                 } else {
                     to[minKey] = this[translationFn](from[key], this._values);
                 }
             }
         },
 
-		/**
-		 * Minifies value based on a dictionary
-		 *
-		 * @param   {String|Boolean} value
-		 * @param   {Array<String|Boolean>} dictionary
-		 *
-		 * @returns {String} The minified version
-		 */
+        /**
+         * Minifies value based on a dictionary
+         *
+         * @param   {String|Boolean} value
+         * @param   {Array<String|Boolean>} dictionary
+         *
+         * @returns {String} The minified version
+         */
         _min: function (value, dictionary) {
-			/**
-			 * If a value actually is a single character, prefix it
-			 * with ___ to avoid mistaking it for a minification code
-			 */
+            /**
+             * If a value actually is a single character, prefix it
+             * with ___ to avoid mistaking it for a minification code
+             */
             if (typeof value === 'string' && value.length === 1) {
                 return '___' + value;
             }
 
             var index = lm.utils.indexOf(value, dictionary);
 
-			/**
-			 * value not found in the dictionary, return it unmodified
-			 */
+            /**
+             * value not found in the dictionary, return it unmodified
+             */
             if (index === -1) {
                 return value;
 
-				/**
-				 * value found in dictionary, return its base36 counterpart
-				 */
+                /**
+                 * value found in dictionary, return its base36 counterpart
+                 */
             } else {
                 return index.toString(36);
             }
         },
 
         _max: function (value, dictionary) {
-			/**
-			 * value is a single character. Assume that it's a translation
-			 * and return the original value from the dictionary
-			 */
+            /**
+             * value is a single character. Assume that it's a translation
+             * and return the original value from the dictionary
+             */
             if (typeof value === 'string' && value.length === 1) {
                 return dictionary[parseInt(value, 36)];
             }
 
-			/**
-			 * value originally was a single character and was prefixed with ___
-			 * to avoid mistaking it for a translation. Remove the prefix
-			 * and return the original character
-			 */
+            /**
+             * value originally was a single character and was prefixed with ___
+             * to avoid mistaking it for a translation. Remove the prefix
+             * and return the original character
+             */
             if (typeof value === 'string' && value.substr(0, 3) === '___') {
                 return value[3];
             }
-			/**
-			 * value was not minified
-			 */
+            /**
+             * value was not minified
+             */
             return value;
         }
     });
 
-	/**
-	 * An EventEmitter singleton that propagates events
-	 * across multiple windows. This is a little bit trickier since
-	 * windows are allowed to open childWindows in their own right
-	 *
-	 * This means that we deal with a tree of windows. Hence the rules for event propagation are:
-	 *
-	 * - Propagate events from this layout to both parents and children
-	 * - Propagate events from parent to this and children
-	 * - Propagate events from children to the other children (but not the emitting one) and the parent
-	 *
-	 * @constructor
-	 *
-	 * @param {lm.LayoutManager} layoutManager
-	 */
+    /**
+     * An EventEmitter singleton that propagates events
+     * across multiple windows. This is a little bit trickier since
+     * windows are allowed to open childWindows in their own right
+     *
+     * This means that we deal with a tree of windows. Hence the rules for event propagation are:
+     *
+     * - Propagate events from this layout to both parents and children
+     * - Propagate events from parent to this and children
+     * - Propagate events from children to the other children (but not the emitting one) and the parent
+     *
+     * @constructor
+     *
+     * @param {lm.LayoutManager} layoutManager
+     */
     lm.utils.EventHub = function (layoutManager) {
         lm.utils.EventEmitter.call(this);
         this._layoutManager = layoutManager;
@@ -5195,15 +5192,15 @@
         $(window).on('gl_child_event', this._boundOnEventFromChild);
     };
 
-	/**
-	 * Called on every event emitted on this eventHub, regardles of origin.
-	 *
-	 * @private
-	 *
-	 * @param {Mixed}
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * Called on every event emitted on this eventHub, regardles of origin.
+     *
+     * @private
+     *
+     * @param {Mixed}
+     *
+     * @returns {void}
+     */
     lm.utils.EventHub.prototype._onEventFromThis = function () {
         var args = Array.prototype.slice.call(arguments);
 
@@ -5217,40 +5214,40 @@
         this._childEventSource = null;
     };
 
-	/**
-	 * Called by the parent layout.
-	 *
-	 * @param   {Array} args Event name + arguments
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * Called by the parent layout.
+     *
+     * @param   {Array} args Event name + arguments
+     *
+     * @returns {void}
+     */
     lm.utils.EventHub.prototype._$onEventFromParent = function (args) {
         this._dontPropagateToParent = args[0];
         this.emit.apply(this, args);
     };
 
-	/**
-	 * Callback for child events raised on the window
-	 *
-	 * @param   {DOMEvent} event
-	 * @private
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * Callback for child events raised on the window
+     *
+     * @param   {DOMEvent} event
+     * @private
+     *
+     * @returns {void}
+     */
     lm.utils.EventHub.prototype._onEventFromChild = function (event) {
         this._childEventSource = event.originalEvent.__gl;
         this.emit.apply(this, event.originalEvent.__glArgs);
     };
 
-	/**
-	 * Propagates the event to the parent by emitting
-	 * it on the parent's DOM window
-	 *
-	 * @param   {Array} args Event name + arguments
-	 * @private
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * Propagates the event to the parent by emitting
+     * it on the parent's DOM window
+     *
+     * @param   {Array} args Event name + arguments
+     * @private
+     *
+     * @returns {void}
+     */
     lm.utils.EventHub.prototype._propagateToParent = function (args) {
         var event,
             eventName = 'gl_child_event';
@@ -5274,14 +5271,14 @@
         }
     };
 
-	/**
-	 * Propagate events to children
-	 *
-	 * @param   {Array} args Event name + arguments
-	 * @private
-	 *
-	 * @returns {void}
-	 */
+    /**
+     * Propagate events to children
+     *
+     * @param   {Array} args Event name + arguments
+     * @private
+     *
+     * @returns {void}
+     */
     lm.utils.EventHub.prototype._propagateToChildren = function (args) {
         var childGl, i;
 
@@ -5295,25 +5292,25 @@
     };
 
 
-	/**
-	 * Destroys the EventHub
-	 *
-	 * @public
-	 * @returns {void}
-	 */
+    /**
+     * Destroys the EventHub
+     *
+     * @public
+     * @returns {void}
+     */
 
     lm.utils.EventHub.prototype.destroy = function () {
         $(window).off('gl_child_event', this._boundOnEventFromChild);
     };
-	/**
-	 * A specialised GoldenLayout component that binds GoldenLayout container
-	 * lifecycle events to react components
-	 *
-	 * @constructor
-	 *
-	 * @param {lm.container.ItemContainer} container
-	 * @param {Object} state state is not required for react components
-	 */
+    /**
+     * A specialised GoldenLayout component that binds GoldenLayout container
+     * lifecycle events to react components
+     *
+     * @constructor
+     *
+     * @param {lm.container.ItemContainer} container
+     * @param {Object} state state is not required for react components
+     */
     lm.utils.ReactComponentHandler = function (container, state) {
         this._reactComponent = null;
         this._originalComponentWillUpdate = null;
@@ -5326,15 +5323,15 @@
 
     lm.utils.copy(lm.utils.ReactComponentHandler.prototype, {
 
-		/**
-		 * Creates the react class and component and hydrates it with
-		 * the initial state - if one is present
-		 *
-		 * By default, react's getInitialState will be used
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Creates the react class and component and hydrates it with
+         * the initial state - if one is present
+         *
+         * By default, react's getInitialState will be used
+         *
+         * @private
+         * @returns {void}
+         */
         _render: function () {
             this._reactComponent = ReactDOM.render(this._getReactComponent(), this._container.getElement()[0]);
             this._originalComponentWillUpdate = this._reactComponent.componentWillUpdate || function () {
@@ -5345,36 +5342,36 @@
             }
         },
 
-		/**
-		 * Removes the component from the DOM and thus invokes React's unmount lifecycle
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Removes the component from the DOM and thus invokes React's unmount lifecycle
+         *
+         * @private
+         * @returns {void}
+         */
         _destroy: function () {
             ReactDOM.unmountComponentAtNode(this._container.getElement()[0]);
             this._container.off('open', this._render, this);
             this._container.off('destroy', this._destroy, this);
         },
 
-		/**
-		 * Hooks into React's state management and applies the componentstate
-		 * to GoldenLayout
-		 *
-		 * @private
-		 * @returns {void}
-		 */
+        /**
+         * Hooks into React's state management and applies the componentstate
+         * to GoldenLayout
+         *
+         * @private
+         * @returns {void}
+         */
         _onUpdate: function (nextProps, nextState) {
             this._container.setState(nextState);
             this._originalComponentWillUpdate.call(this._reactComponent, nextProps, nextState);
         },
 
-		/**
-		 * Retrieves the react class from GoldenLayout's registry
-		 *
-		 * @private
-		 * @returns {React.Class}
-		 */
+        /**
+         * Retrieves the react class from GoldenLayout's registry
+         *
+         * @private
+         * @returns {React.Class}
+         */
         _getReactClass: function () {
             var componentName = this._container._config.component;
             var reactClass;
@@ -5393,12 +5390,12 @@
             return reactClass;
         },
 
-		/**
-		 * Copies and extends the properties array and returns the React element
-		 *
-		 * @private
-		 * @returns {React.Element}
-		 */
+        /**
+         * Copies and extends the properties array and returns the React element
+         *
+         * @private
+         * @returns {React.Element}
+         */
         _getReactComponent: function () {
             var defaultProps = {
                 glEventHub: this._container.layoutManager.eventHub,
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index ba1c91720..d913f2069 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -117,7 +117,7 @@
 
 .mainView-propertiesDragger {
     //background-color: rgb(140, 139, 139);
-    background-color: $medium-gray;
+    background-color: $light-gray;
     height: 55px;
     width: 17px;
     position: absolute;
@@ -165,7 +165,7 @@
         left: 0;
         position: absolute;
         z-index: 2;
-        background-color: $medium-gray;
+        background-color: $light-gray;
         .editable-title {
             background-color: $light-gray;
         }
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index e2d27d5a6..ce6636080 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -75,6 +75,20 @@
             display: flex;
             justify-content: flex-end;
 
+            
+
+            
+
+        }
+
+        .topbar-left {
+            grid-column: 1;
+            color: black;
+            font-family: 'Roboto';
+            position: relative;
+            display: flex;
+            width: 450;
+
             .topbar-lozenge-user,
             .topbar-lozenge {
                 height: 23;
@@ -89,20 +103,6 @@
                 align-items: center;
                 border: white 1px solid;
 
-                .topbar-logoff {
-                    border-radius: 3px;
-                    background: olivedrab;
-                    color: white;
-                    display: none;
-                    margin-left: 5px;
-                    padding: 1px 2px 1px 2px;
-                    cursor: pointer;
-                }
-
-                .topbar-logoff {
-                    background: red;
-                }
-
                 .topbar-dashSelect {
                     border: none;
                     background-color: transparent;
@@ -117,21 +117,25 @@
                 }
             }
 
+            .topbar-logoff {
+                border-radius: 3px;
+                background: olivedrab;
+                color: white;
+                display: none;
+                margin-left: 5px;
+                padding: 1px 2px 1px 2px;
+                cursor: pointer;
+            }
+
+            .topbar-logoff {
+                background: red;
+            }
+
             .topbar-lozenge-user:hover {
                 .topbar-logoff {
                     display: inline-block;
                 }
             }
-
-        }
-
-        .topbar-left {
-            grid-column: 1;
-            color: black;
-            font-family: 'Roboto';
-            position: relative;
-            display: flex;
-            width: 450;
         }
 
         .topbar-barChild {
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 65da717f8..02b597078 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -24,6 +24,14 @@ export class TopBar extends React.Component {
             //TODO:glr Add support for light / dark mode
             <div style={{ pointerEvents: "all" }} className="topbar-container">
                 <div className="topbar-bar" style={{ background: Colors.DARK_GRAY, borderBottom: Borders.STANDARD }}>
+                    <div className="topbar-left">
+                        <div className="topbar-lozenge-user">
+                            {`${Doc.CurrentUserEmail}`}
+                            <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+                                Logoff
+                            </div>
+                        </div>
+                    </div>
                     <div className="topbar-center" >
                         <div className="topbar-lozenge-dashboard">
                             <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
@@ -34,11 +42,11 @@ export class TopBar extends React.Component {
                             <div className="topbar-dashboards">
                                 <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
                                     style={{ color: Colors.WHITE }}>
-                                    <FontAwesomeIcon icon="plus"></FontAwesomeIcon>
+                                    <FontAwesomeIcon icon="plus"></FontAwesomeIcon>{"New"}
                                 </div>
                                 <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
                                     style={{ color: Colors.WHITE }}>
-                                    <FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+                                    <FontAwesomeIcon icon="camera"></FontAwesomeIcon>{"Snapshot"}
                                 </div>
                             </div>
                         </div>
@@ -52,15 +60,9 @@ export class TopBar extends React.Component {
                             style={{ color: Colors.WHITE }}>
                             <FontAwesomeIcon icon="cog"></FontAwesomeIcon>
                         </div>
-                        <div className="topbar-lozenge-user">
-                            {`${Doc.CurrentUserEmail}`}
-                            <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
-                                Logoff
-                        </div>
-                        </div>
-                    </div>
 
-                </div >
+                    </div>
+                </div>
             </div >
         );
     }
diff --git a/src/client/views/topbar/TopBarButton.tsx b/src/client/views/topbar/TopBarButton.tsx
deleted file mode 100644
index 0d3d2a8d1..000000000
--- a/src/client/views/topbar/TopBarButton.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import React from "react";
-
-export interface IButtonProps {
-    icon?: JSX.Element;
-    text?: String;
-}
-
-export class TopBarButton implements IButtonProps {
-
-}
-- 
cgit v1.2.3-70-g09d2


From fcc75a92643f35955a1e0bbe829e96b0e76c8a4e Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Sat, 31 Jul 2021 08:09:45 -0400
Subject: updates ready for sprint (almost)

---
 src/client/goldenLayout.js                         | 37 +++++++--------
 src/client/views/DocumentButtonBar.scss            |  6 +--
 src/client/views/_nodeModuleOverrides.scss         |  3 +-
 .../views/collections/CollectionDockingView.scss   |  6 +--
 src/client/views/global/globalCssVariables.scss    |  2 +
 src/client/views/topbar/TopBar.scss                | 52 +++++++++++-----------
 src/client/views/topbar/TopBar.tsx                 | 34 +++++++-------
 7 files changed, 69 insertions(+), 71 deletions(-)

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index b118a5f44..238f1ac0a 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -1571,11 +1571,11 @@
             tabControlOffset: 10
         },
         dimensions: {
-            borderWidth: 5,
+            borderWidth: 3,
             borderGrabWidth: 5,
             minItemHeight: 10,
-            minItemWidth: 10,
-            headerHeight: 22,
+            minItemWidth: 20,
+            headerHeight: 27,
             dragProxyWidth: 300,
             dragProxyHeight: 200
         },
@@ -2477,20 +2477,21 @@
                 }
             }
 
-            if (this.layoutManager.config.settings.reorderOnTabMenuClick) {
-                /**
-                 * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
-                 * This will make sure the most used tabs stay visible.
-                 */
-                if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) {
-                    activeTab = this.tabs[this.parent.config.activeItemIndex];
-                    for (j = this.parent.config.activeItemIndex; j > 0; j--) {
-                        this.tabs[j] = this.tabs[j - 1];
-                    }
-                    this.tabs[0] = activeTab;
-                    this.parent.config.activeItemIndex = 0;
-                }
-            }
+            // glr: removed for new tab manager
+            // if (this.layoutManager.config.settings.reorderOnTabMenuClick) {
+            //     /**
+            //      * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first.
+            //      * This will make sure the most used tabs stay visible.
+            //      */
+            //     if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) {
+            //         activeTab = this.tabs[this.parent.config.activeItemIndex];
+            //         for (j = this.parent.config.activeItemIndex; j > 0; j--) {
+            //             this.tabs[j] = this.tabs[j - 1];
+            //         }
+            //         this.tabs[0] = activeTab;
+            //         this.parent.config.activeItemIndex = 0;
+            //     }
+            // }
 
             this._updateTabSizes();
             this.parent.emitBubblingEvent('stateChanged');
@@ -4872,7 +4873,7 @@
                 this.layoutManager.dropTargetIndicator.highlightArea({
                     x1: headerOffset.left,
                     x2: headerOffset.left + 100,
-                    y1: headerOffset.top + this.header.element.height() - 20,
+                    y1: headerOffset.top + this.header.element.height() - 25,
                     y2: headerOffset.top + this.header.element.height()
                 });
 
diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index 2a0b494f5..621c2bf1b 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -44,18 +44,16 @@ $linkGap : 3px;
 }
 
 .documentButtonBar {
-    margin-top: $linkGap;
-    grid-column: 1/4;
-    width: max-content;
-    height: auto;
     display: flex;
     flex-direction: row;
+    gap: 3px;
 }
 
 .documentButtonBar-button {
     pointer-events: auto;
     padding-right: 5px;
     width: 25px;
+    height: 25px;
 }
 
 .documentButtonBar-linker {
diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss
index 140be2140..fd0ac9d5c 100644
--- a/src/client/views/_nodeModuleOverrides.scss
+++ b/src/client/views/_nodeModuleOverrides.scss
@@ -5,6 +5,7 @@
 div .lm_header {
     background: $dark-gray;
     overflow: hidden;
+    height: 27px !important;
 }
 
 /* Width */
@@ -62,7 +63,7 @@ div .lm_header {
     border-radius: 5px;
     display: flex;
     justify-content: space-evenly;
-    height: 18px;
+    height: 23px;
     width: 65px;
 }
 
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index b8180fe24..77e7b86ea 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -39,7 +39,7 @@
     padding: 0px;
     opacity: 0.7;
     box-shadow: none;
-    height: 19px;
+    height: 24px;
     // border-bottom: 1px black;
 
     .collectionDockingView-gear {
@@ -52,7 +52,7 @@
     opacity: 1;
     margin: 0;
     box-shadow: none;
-    height: 22px;
+    height: 27px;
     margin-right: 2px;
     // border-bottom: unset;
 
@@ -357,8 +357,6 @@
         background: transparent url("../../../../node_modules/flexlayout-react/images/restore.png") no-repeat center;
     }
 
-    .flexlayout__popup_menu {}
-
     .flexlayout__popup_menu_item {
         padding: 2px 10px 2px 10px;
         color: #ddd;
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index 72adc171b..a9f33c4da 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -11,6 +11,8 @@ $medium-blue: #4476F7;
 $pink: #E0217D;
 $yellow: #F5D747;
 
+$logout-red: #ca4444;
+
 $drop-shadow: "#32323215";
 
 //padding
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index ce6636080..adb968948 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -20,11 +20,34 @@
         align-items: center;
         background-color: $dark-gray;
 
+        .topBar-icon {
+            cursor: pointer;
+            font-size: 12px;
+            width: fit-content;
+            display: flex;
+            justify-content: center;
+            gap: 4px;
+            align-items: center;
+            justify-self: center;
+            align-self: center;
+            border-radius: 5px;
+            padding: 5px;
+            transition: linear 0.1s;
+            color: $black;
+            background-color: $light-gray;
+        }
+
+        .topBar-icon:hover {
+            background-color: $light-blue;
+        }
+
+        
         .topbar-center {
             grid-column: 2;
             display: inline-flex;
             justify-content: center;
             align-items: center;
+            gap: 5px;
 
             .topbar-lozenge-dashboard {
                 display: flex;
@@ -48,37 +71,13 @@
             }
         }
 
-        .topBar-icon {
-            color: black;
-            cursor: pointer;
-            font-size: 15px;
-            height: 30;
-            width: 30;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            margin-right: 5px;
-            justify-self: center;
-            align-self: center;
-            border-radius: 100%;
-            transition: linear 0.1s;
-            background-color: #92adb900;
-        }
-
-        .topBar-icon:hover {
-            background-color: rgba(0, 0, 0, 0.15);
-        }
 
         .topbar-right {
             grid-column: 3;
             position: relative;
             display: flex;
             justify-content: flex-end;
-
-            
-
-            
-
+            gap: 5px;
         }
 
         .topbar-left {
@@ -88,6 +87,7 @@
             position: relative;
             display: flex;
             width: 450;
+            gap: 5px;
 
             .topbar-lozenge-user,
             .topbar-lozenge {
@@ -98,10 +98,10 @@
                 font-weight: 400;
                 padding: 4px;
                 align-self: center;
+                margin-left: 7px;
                 margin-right: 7px;
                 display: flex;
                 align-items: center;
-                border: white 1px solid;
 
                 .topbar-dashSelect {
                     border: none;
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 02b597078..6e4d4fe15 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -27,9 +27,9 @@ export class TopBar extends React.Component {
                     <div className="topbar-left">
                         <div className="topbar-lozenge-user">
                             {`${Doc.CurrentUserEmail}`}
-                            <div className="topbar-logoff" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
-                                Logoff
-                            </div>
+                        </div>
+                        <div className="topbar-icon" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+                            {"Logoff"}<FontAwesomeIcon icon="sign-out"></FontAwesomeIcon>
                         </div>
                     </div>
                     <div className="topbar-center" >
@@ -39,26 +39,24 @@ export class TopBar extends React.Component {
                                 style={{ color: Colors.WHITE }}>
                                 {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
                             </select>
-                            <div className="topbar-dashboards">
-                                <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
-                                    style={{ color: Colors.WHITE }}>
-                                    <FontAwesomeIcon icon="plus"></FontAwesomeIcon>{"New"}
-                                </div>
-                                <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
-                                    style={{ color: Colors.WHITE }}>
-                                    <FontAwesomeIcon icon="camera"></FontAwesomeIcon>{"Snapshot"}
-                                </div>
+                        </div>
+                        <div className="topbar-dashboards">
+                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
+                            >
+                                {"New"}<FontAwesomeIcon icon="plus"></FontAwesomeIcon>
                             </div>
+                            {Doc.UserDoc().noviceMode ? (null) : <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
+                            >
+                                {"Snapshot"}<FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+                            </div>}
                         </div>
                     </div>
                     <div className="topbar-right" >
-                        <div className="topbar-icon"
-                            style={{ color: Colors.WHITE }}>
-                            <FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
+                        <div className="topbar-icon">
+                            {"Help"}<FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
                         </div>
-                        <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}
-                            style={{ color: Colors.WHITE }}>
-                            <FontAwesomeIcon icon="cog"></FontAwesomeIcon>
+                        <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}>
+                            {"Settings"}<FontAwesomeIcon icon="cog"></FontAwesomeIcon>
                         </div>
 
                     </div>
-- 
cgit v1.2.3-70-g09d2


From 41ccf50f2b551edd6827c9fd6296b9ff87a65915 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Sat, 31 Jul 2021 15:32:37 -0400
Subject: linking updates and tab updates

---
 deploy/index.html                               | 105 +++++++++++++++++++++++-
 src/client/views/DocumentButtonBar.scss         |  11 ++-
 src/client/views/DocumentDecorations.scss       |   4 +-
 src/client/views/collections/TabDocView.tsx     |   7 +-
 src/client/views/nodes/DocumentLinksButton.scss |  15 +++-
 src/client/views/nodes/DocumentLinksButton.tsx  |  83 ++++++++++---------
 src/client/views/nodes/DocumentView.scss        |   2 +-
 src/client/views/topbar/TopBar.scss             |  10 ++-
 src/client/views/topbar/TopBar.tsx              |   2 +-
 9 files changed, 182 insertions(+), 57 deletions(-)

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/deploy/index.html b/deploy/index.html
index d96215391..c32aff638 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -11,8 +11,109 @@
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
         integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
     <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script>
-    <script src="loader.js"></script>
-    <link rel="stylesheet" href="./loader.css" />
+    <script>
+        function getCookie(cname) {
+            var name = cname + "=";
+            var ca = document.cookie.split(';');
+            for (var i = 0; i < ca.length; i++) {
+                var c = ca[i];
+                while (c.charAt(0) == ' ') {
+                    c = c.substring(1);
+                }
+                if (c.indexOf(name) == 0) {
+                    return Number(c.substring(name.length, c.length));
+                }
+            }
+            return 3000;
+        }
+    </script>
+    <style>
+        .dash-loader {
+            display: flex;
+            align-content: center;
+            justify-content: center;
+            background-color: #BDDDF5;
+            transition: 3s;
+            z-index: 10;
+            z-index: 10;
+            width: 100%;
+            height: 100%;
+        }
+
+        .dash-loader-container {
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            align-content: center;
+        }
+
+        .dash-progress-bar {
+            width: 200px;
+            height: 5px;
+            align-self: center;
+            margin-top: 20px;
+            background-color: #ececec;
+            border-radius: 5px;
+            overflow: hidden;
+        }
+
+        .dash-progress {
+            width: 0%;
+            height: 20px;
+            background-color: #4476F7;
+            transition: 0.1s;
+        }
+
+        .dash-animation-container {
+            width: 10vw;
+            height: 10vw;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border-radius: 100%;
+            background-color: #4476F7;
+            justify-self: center;
+        }
+
+        .dash-loader-text {
+            font-size: 15px;
+            font-family: "Roboto";
+            font-weight: 400;
+            text-align: center;
+            color: #4476F7;
+            user-select: none;
+            -webkit-user-select: none;
+        }
+
+        .dash-d-path {
+            stroke-dasharray: 1000;
+            stroke-dashoffset: 1000;
+            animation: dash-d-path 3s linear infinite;
+        }
+
+        @keyframes dash-d-path {
+            0% {
+                stroke-dashoffset: 1000;
+            }
+
+            20% {
+                stroke-dashoffset: 0;
+            }
+
+            70% {
+                stroke-dashoffset: 0;
+            }
+
+            90% {
+                stroke-dashoffset: 1000;
+            }
+
+            100% {
+                stroke-dashoffset: 1000;
+            }
+        }
+    </style>
 </head>
 
 <body style="display:flex" id="dash-body">
diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index 621c2bf1b..157f3a4f2 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -50,10 +50,13 @@ $linkGap : 3px;
 }
 
 .documentButtonBar-button {
-    pointer-events: auto;
-    padding-right: 5px;
-    width: 25px;
-    height: 25px;
+    cursor: pointer;
+    display: flex;
+    width: 30px;
+    height: 30px;
+    align-content: center;
+    justify-content: center;
+    align-items: center;
 }
 
 .documentButtonBar-linker {
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 1715f35e7..952d8d150 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -263,7 +263,6 @@ $linkGap : 3px;
 }
 
 .link-button-container {
-    padding: $linkGap;
     border-radius: 10px;
     width: max-content;
     height: auto;
@@ -271,6 +270,9 @@ $linkGap : 3px;
     flex-direction: row;
     z-index: 998;
     position: absolute;
+    justify-content: center;
+    align-items: center;
+    gap: 5px;
     background: $medium-gray;
 }
 
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d82810652..a24f1eb7a 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -169,7 +169,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 }));
 
             //attach the selection doc buttons menu to the drag handle
-            const stack = tab.contentItem.parent;
+            const stack: HTMLDivElement = tab.contentItem.parent;
+            const header: HTMLDivElement = tab;
+            console.log("Stack: " + stack.id, stack.className)
+            stack.onscroll = action((e: any) => {
+                console.log('scrolling...')
+            })
             const moreInfoDrag = document.createElement("div");
             moreInfoDrag.className = "lm_iconWrap";
             tab._disposers.buttonDisposer = reaction(() => this.view, view =>
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 3809319d7..9bab72d55 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -1,6 +1,16 @@
 @import "../global/globalCssVariables.scss";
 
 
+.documentLinksButton-menu {
+    width: 100%;
+    height: 100%;
+    position: relative;
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    align-items: center;
+}
+
 .documentLinksButton-cont {
     min-width: 20;
     min-height: 20;
@@ -10,8 +20,8 @@
 .documentLinksButton,
 .documentLinksButton-endLink,
 .documentLinksButton-startLink {
-    height: 20px;
-    width: 20px;
+    height: 25px;
+    width: 25px;
     position: absolute;
     border-radius: 50%;
     opacity: 0.9;
@@ -38,7 +48,6 @@
     font-weight: bold;
 
     &:hover {
-        background: $medium-gray;
         transform: scale(1.05);
         cursor: pointer;
     }
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index ed0e2d1ad..cec06d2d4 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -252,49 +252,50 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         const btnDim = this.props.InMenu ? "20px" : "30px";
         const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
 
-        return <div className="documentLinksButton-cont" ref={this._linkButton}
-            style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
-        >
-            <div className={"documentLinksButton"}
-                onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
-                style={{
-                    backgroundColor: this.props.InMenu ? "" : Colors.LIGHT_BLUE,
-                    color: this.props.InMenu ? Colors.WHITE : "black",
-                    width: btnDim,
-                    height: btnDim,
-                }} >
-                {this.props.InMenu ?
-                    this.props.StartLink ?
-                        <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
-                        : link
-                    : Array.from(this.filteredLinks).length}
-            </div>
-            {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
-                <div className={"documentLinksButton-endLink"}
+        return (!this.props.InMenu ?
+            <div className="documentLinksButton-cont" ref={this._linkButton}
+                style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
+            >
+                <div className={"documentLinksButton"}
+                    onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
                     style={{
-                        width: btnDim, height: btnDim,
-                        backgroundColor: DocumentLinksButton.StartLink ? "" : Colors.LIGHT_GRAY,
-                        opacity: DocumentLinksButton.StartLink ? "" : "50%",
-                        border: DocumentLinksButton.StartLink ? "" : "none",
-                        cursor: DocumentLinksButton.StartLink ? "pointer" : "default"
-                    }}
-                    onPointerDown={DocumentLinksButton.StartLink && this.completeLink}
-                    onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}>
-                    {this.props.StartLink ?
-                        <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
-                        : link}
-                </div>
-                : (null)
-            }
-            {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
-                <div className={"documentLinksButton-startLink"} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }}>
-                    {this.props.StartLink ?
-                        <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
-                        : link}
+                        backgroundColor: Colors.LIGHT_BLUE,
+                        color: Colors.BLACK,
+                        width: btnDim,
+                        height: btnDim,
+                    }}>
+                    {Array.from(this.filteredLinks).length}
                 </div>
-                : (null)
-            }
-        </div >;
+            </div>
+            :
+            <div className="documentLinksButton-menu">
+                {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
+                    <div className={"documentLinksButton-endLink"}
+                        style={{
+                            width: btnDim, height: btnDim,
+                            backgroundColor: DocumentLinksButton.StartLink ? "" : Colors.LIGHT_GRAY,
+                            opacity: DocumentLinksButton.StartLink ? "" : "50%",
+                            border: DocumentLinksButton.StartLink ? "" : "none",
+                            cursor: DocumentLinksButton.StartLink ? "pointer" : "default"
+                        }}
+                        onPointerDown={DocumentLinksButton.StartLink && this.completeLink}
+                        onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}>
+                        {this.props.StartLink ?
+                            <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
+                            : link}
+                    </div>
+                    : (null)
+                }
+                {
+                    this.props.InMenu ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+                        <div className={'documentLinksButton' + (DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink) ? '-startLink' : ''} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }}>
+                            {this.props.StartLink ?
+                                <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
+                                : link}
+                        </div>
+                        : (null)}
+            </div>
+        )
     }
 
     render() {
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 281f25fb3..7f164ca48 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -147,7 +147,7 @@
         .documentView-titleWrapper,
         .documentView-titleWrapper-hover {
             overflow: hidden;
-            color: gray;
+            color: $black;
             transform-origin: top left;
             top: 0;
             width: 100%;
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index adb968948..ebdf030e7 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -58,8 +58,8 @@
 
                 .topbar-dashSelect {
                     border: none;
-                    background-color: transparent;
-                    color: black;
+                    background-color: $dark-gray;
+                    color: $white;
                     font-family: 'Roboto';
                     font-size: 17;
                     font-weight: 500;
@@ -78,6 +78,7 @@
             display: flex;
             justify-content: flex-end;
             gap: 5px;
+            margin-right: 5px;
         }
 
         .topbar-left {
@@ -89,6 +90,10 @@
             width: 450;
             gap: 5px;
 
+            .topBar-icon:hover {
+                background-color: $logout-red;
+            }
+
             .topbar-lozenge-user,
             .topbar-lozenge {
                 height: 23;
@@ -99,7 +104,6 @@
                 padding: 4px;
                 align-self: center;
                 margin-left: 7px;
-                margin-right: 7px;
                 display: flex;
                 align-items: center;
 
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 6e4d4fe15..bd9935333 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -29,7 +29,7 @@ export class TopBar extends React.Component {
                             {`${Doc.CurrentUserEmail}`}
                         </div>
                         <div className="topbar-icon" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
-                            {"Logoff"}<FontAwesomeIcon icon="sign-out"></FontAwesomeIcon>
+                            {"Sign out"}
                         </div>
                     </div>
                     <div className="topbar-center" >
-- 
cgit v1.2.3-70-g09d2


From d3a7e378e26466b911733f76addfe9fc61a689df Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Sat, 31 Jul 2021 18:17:35 -0400
Subject: fixed linking issues with dragging & updating linking UI

---
 src/client/views/DocumentButtonBar.scss            |  21 +++++
 src/client/views/DocumentButtonBar.tsx             |  26 +++---
 src/client/views/DocumentDecorations.scss          |   2 +-
 .../views/collections/CollectionLinearView.scss    |   8 +-
 src/client/views/global/globalCssVariables.scss    |   2 +-
 src/client/views/nodes/DocumentLinksButton.scss    |  38 ++++++--
 src/client/views/nodes/DocumentLinksButton.tsx     | 102 ++++++++++-----------
 src/client/views/topbar/TopBar.scss                |   3 +-
 src/client/views/topbar/TopBar.tsx                 |   1 -
 9 files changed, 119 insertions(+), 84 deletions(-)

(limited to 'src/client/views/topbar/TopBar.tsx')

diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index 157f3a4f2..171e7134f 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -59,6 +59,7 @@ $linkGap : 3px;
     align-items: center;
 }
 
+// depracated (now use .documentButtonBar-icon) for standard buttons
 .documentButtonBar-linker {
     height: 20px;
     width: 20px;
@@ -74,6 +75,26 @@ $linkGap : 3px;
     }
 }
 
+.documentButtonBar-icon {
+    height: 80%;
+    width: 80%;
+    font-size: 100%;
+    text-align: center;
+    border-radius: 50%;
+    pointer-events: auto;
+    background-color: $dark-gray;
+    border: none;
+    transition: 0.2s ease all;
+    display: flex;
+    align-content: center;
+    justify-content: center;
+    align-items: center;
+
+    &:hover {
+        background-color: $black;
+    }
+}
+
 .documentButtonBar-linker:hover {
     cursor: pointer;
     transform: scale(1.05);
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 1e5380971..df1e6899d 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -110,7 +110,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
             <div
-                className="documentButtonBar-linker"
+                className="documentButtonBar-button"
                 style={{ animation }}
                 onClick={async () => {
                     await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
@@ -139,7 +139,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
 
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{title}</div></>}>
-            <div className="documentButtonBar-linker"
+            <div className="documentButtonBar-button"
                 style={{ backgroundColor: this.pullColor }}
                 onPointerEnter={action(e => {
                     if (e.altKey) {
@@ -188,8 +188,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={
             <div className="dash-tooltip">{"follow primary link on click"}</div>}>
-            <div className="documentButtonBar-linker"
-                style={{ color: targetDoc.isLinkButton ? "black" : "white", backgroundColor: targetDoc.isLinkButton ? "white" : "black" }}
+            <div className="documentButtonBar-icon"
+                style={{ color: targetDoc.isLinkButton ? "black" : "white" }}
                 onClick={undoBatch(e => this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, false, false)))}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="hand-point-right" />
             </div>
@@ -200,7 +200,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={
             <div className="dash-tooltip">{SelectionManager.Views().length > 1 ? "Pin multiple documents to presentation" : "Pin to presentation"}</div>}>
-            <div className="documentButtonBar-linker"
+            <div className="documentButtonBar-icon"
                 style={{ color: "white" }}
                 onClick={undoBatch(e => this.props.views().map(view => view && TabDocView.PinDoc(view.props.Document, { setPosition: e.shiftKey ? true : undefined })))}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
@@ -243,7 +243,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: "auto", width: 17, transform: 'translate(0, 1px)' }} />;
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with current view"}</div></>}>
-            <div className="documentButtonBar-linker" onClick={() => this.pinWithView(targetDoc)}>
+            <div className="documentButtonBar-icon" onClick={() => this.pinWithView(targetDoc)}>
                 {presPinWithViewIcon}
             </div>
         </Tooltip>;
@@ -253,8 +253,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get shareButton() {
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Open Sharing Manager"}</div></>}>
-            <div className="documentButtonBar-linker" style={{ color: "white" }} onClick={e => SharingManager.Instance.open(this.view0, targetDoc)}>
-                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="users" />
+            <div className="documentButtonBar-icon" style={{ color: "white" }} onClick={e => SharingManager.Instance.open(this.view0, targetDoc)}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon="users" />
             </div></Tooltip >;
     }
 
@@ -262,8 +262,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get menuButton() {
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`Open Context Menu`}</div></>}>
-            <div className="documentButtonBar-linker" style={{ color: "white", cursor: "pointer" }} onClick={e => this.openContextMenu(e)}>
-                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="bars" />
+            <div className="documentButtonBar-icon" style={{ color: "white", cursor: "pointer" }} onClick={e => this.openContextMenu(e)}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon="bars" />
             </div></Tooltip >;
     }
 
@@ -271,9 +271,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get moreButton() {
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${CurrentUserUtils.propertiesWidth > 0 ? "Close" : "Open"} Properties Panel`}</div></>}>
-            <div className="documentButtonBar-linker" style={{ color: "white", cursor: "e-resize" }} onClick={action(e =>
+            <div className="documentButtonBar-icon" style={{ color: "white", cursor: "e-resize" }} onClick={action(e =>
                 CurrentUserUtils.propertiesWidth = CurrentUserUtils.propertiesWidth > 0 ? 0 : 250)}>
-                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="ellipsis-h"
+                <FontAwesomeIcon className="documentdecorations-icon" icon="ellipsis-h"
                 />
             </div></Tooltip >;
     }
@@ -286,7 +286,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                 <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                     content={<MetadataEntryMenu docs={this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
                     <div className={"documentButtonBar-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" />}
                     </div>
                 </Flyout>
             </div></Tooltip>;
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 952d8d150..316f63240 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -336,7 +336,7 @@ $linkGap : 3px;
 }
 
 .documentdecorations-icon {
-    margin-top: 3px;
+    margin: 0px;
 }
 .templating-button,
 .docDecs-tagButton {
diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss
index 86610ac20..913a65774 100644
--- a/src/client/views/collections/CollectionLinearView.scss
+++ b/src/client/views/collections/CollectionLinearView.scss
@@ -20,7 +20,7 @@
         }
 
         .bottomPopup-background {
-            background: $light-blue;
+            background: $medium-blue;
             display: flex;
             height: 35;
             transform: translate3d(6px, 0px, 0px);
@@ -30,7 +30,7 @@
         }
 
         .bottomPopup-text {
-            color: black;
+            color: $white;
             display: inline;
             white-space: nowrap;
             padding-left: 8px;
@@ -45,7 +45,7 @@
             padding-left: 8px;
             padding-right: 8px;
             vertical-align: middle;
-            background-color: #efefef;
+            background-color: $light-gray;
             border-radius: 3px;
             color: black;
             margin-right: 5px;
@@ -58,7 +58,7 @@
             padding-left: 8px;
             padding-right: 8px;
             vertical-align: middle;
-            background-color: #f3b6b6;
+            background-color: $close-red;
             border-radius: 3px;
             color: black;
         }
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index a9f33c4da..1b881ba43 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -11,7 +11,7 @@ $medium-blue: #4476F7;
 $pink: #E0217D;
 $yellow: #F5D747;
 
-$logout-red: #ca4444;
+$close-red: #e48282;
 
 $drop-shadow: "#32323215";
 
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 9bab72d55..b37b68249 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -44,25 +44,43 @@
 }
 
 .documentLinksButton {
-    background-color: black;
+    background-color: $dark-gray;
+    color: $white;
     font-weight: bold;
+    width: 80%;
+    height: 80%;
+    font-size: 100%;
+    transition: 0.2s ease all;
 
     &:hover {
-        transform: scale(1.05);
-        cursor: pointer;
+        background-color: $black;
+    }
+}
+
+.documentLinksButton.startLink {
+    background-color: $medium-blue;
+    color: $white;
+    font-weight: bold;
+    width: 80%;
+    height: 80%;
+    font-size: 100%;
+    transition: 0.2s ease all;
+
+    &:hover {
+        background-color: $black;
     }
 }
 
 .documentLinksButton-endLink {
     border: $medium-blue 2px dashed;
     color: $medium-blue;
+    background-color: none !important;
+    width: 80%;
+    height: 80%;
+    font-size: 100%;
+    transition: 0.2s ease all;
+
     &:hover {
-        background: $light-gray;
-        transform: scale(1.05);
-        cursor: pointer;
+        background-color: $light-blue;
     }
-}
-
-.documentLinksButton-startLink {
-    background-color: $medium-blue;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index cec06d2d4..482f551b5 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -68,6 +68,40 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         return false;
     }
 
+    onLinkMenuOpen = (e: React.PointerEvent): void => {
+        setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
+            if (doubleTap) {
+                const rootDoc = this.props.View.rootDoc;
+                const docid = Doc.CurrentUserEmail + Doc.GetProto(rootDoc)[Id] + "-pivotish";
+                DocServer.GetRefField(docid).then(async docx => {
+                    const rootAlias = () => {
+                        const rootAlias = Doc.MakeAlias(rootDoc);
+                        rootAlias.x = rootAlias.y = 0;
+                        return rootAlias;
+                    };
+                    let wid = rootDoc[WidthSym]();
+                    const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([rootAlias()], { title: this.props.View.Document.title + "-pivot", _width: 500, _height: 500, }, docid);
+                    const docs = await DocListCastAsync(Doc.GetProto(target).data);
+                    if (!target.pivotFocusish) (Doc.GetProto(target).pivotFocusish = target);
+                    DocListCast(rootDoc.links).forEach(link => {
+                        const other = LinkManager.getOppositeAnchor(link, rootDoc);
+                        const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
+                        if (otherdoc && !docs?.some(d => Doc.AreProtosEqual(d, otherdoc))) {
+                            const alias = Doc.MakeAlias(otherdoc);
+                            alias.x = wid;
+                            alias.y = 0;
+                            alias._lockedPosition = false;
+                            wid += otherdoc[WidthSym]();
+                            Doc.AddDocToList(Doc.GetProto(target), "data", alias);
+                        }
+                    });
+                    LightboxView.SetLightboxDoc(target);
+                });
+            }
+            else DocumentLinksButton.LinkEditorDocView = this.props.View;
+        }));
+    }
+
     @undoBatch
     onLinkButtonDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
@@ -80,37 +114,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     DocumentLinksButton.StartLink = this.props.View.props.Document;
                     DocumentLinksButton.StartLinkView = this.props.View;
                 }
-            } else if (!this.props.InMenu) {
-                if (doubleTap) {
-                    const rootDoc = this.props.View.rootDoc;
-                    const docid = Doc.CurrentUserEmail + Doc.GetProto(rootDoc)[Id] + "-pivotish";
-                    DocServer.GetRefField(docid).then(async docx => {
-                        const rootAlias = () => {
-                            const rootAlias = Doc.MakeAlias(rootDoc);
-                            rootAlias.x = rootAlias.y = 0;
-                            return rootAlias;
-                        };
-                        let wid = rootDoc[WidthSym]();
-                        const target = ((docx instanceof Doc) && docx) || Docs.Create.FreeformDocument([rootAlias()], { title: this.props.View.Document.title + "-pivot", _width: 500, _height: 500, }, docid);
-                        const docs = await DocListCastAsync(Doc.GetProto(target).data);
-                        if (!target.pivotFocusish) (Doc.GetProto(target).pivotFocusish = target);
-                        DocListCast(rootDoc.links).forEach(link => {
-                            const other = LinkManager.getOppositeAnchor(link, rootDoc);
-                            const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other;
-                            if (otherdoc && !docs?.some(d => Doc.AreProtosEqual(d, otherdoc))) {
-                                const alias = Doc.MakeAlias(otherdoc);
-                                alias.x = wid;
-                                alias.y = 0;
-                                alias._lockedPosition = false;
-                                wid += otherdoc[WidthSym]();
-                                Doc.AddDocToList(Doc.GetProto(target), "data", alias);
-                            }
-                        });
-                        LightboxView.SetLightboxDoc(target);
-                    });
-                }
-                else DocumentLinksButton.LinkEditorDocView = this.props.View;
-            }
+            };
         }));
     }
 
@@ -126,7 +130,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 DocumentLinksButton.StartLink = this.props.View.props.Document;
                 DocumentLinksButton.StartLinkView = this.props.View;
             }
-
             //action(() => Doc.BrushDoc(this.props.View.Document));
         } else if (!this.props.InMenu) {
             DocumentLinksButton.LinkEditorDocView = this.props.View;
@@ -247,17 +250,19 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
     /**
      * gets the JSX of the link button (btn used to start/complete links) OR the link-view button (btn on bottom left of each linked node)
+     * 
+     * todo:glr / anh seperate functionality such as onClick onPointerDown of link menu button
      */
     @computed get linkButtonInner() {
-        const btnDim = this.props.InMenu ? "20px" : "30px";
+        const btnDim = "30px";
         const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
-
+        const isActive = (DocumentLinksButton.StartLink === this.props.View.props.Document) && this.props.StartLink;
         return (!this.props.InMenu ?
-            <div className="documentLinksButton-cont" ref={this._linkButton}
+            <div className="documentLinksButton-cont"
                 style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
             >
                 <div className={"documentLinksButton"}
-                    onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
+                    onPointerDown={this.onLinkMenuOpen} onClick={this.onLinkClick}
                     style={{
                         backgroundColor: Colors.LIGHT_BLUE,
                         color: Colors.BLACK,
@@ -268,32 +273,23 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 </div>
             </div>
             :
-            <div className="documentLinksButton-menu">
+            <div className="documentLinksButton-menu" ref={this._linkButton}>
                 {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
                     <div className={"documentLinksButton-endLink"}
-                        style={{
-                            width: btnDim, height: btnDim,
-                            backgroundColor: DocumentLinksButton.StartLink ? "" : Colors.LIGHT_GRAY,
-                            opacity: DocumentLinksButton.StartLink ? "" : "50%",
-                            border: DocumentLinksButton.StartLink ? "" : "none",
-                            cursor: DocumentLinksButton.StartLink ? "pointer" : "default"
-                        }}
                         onPointerDown={DocumentLinksButton.StartLink && this.completeLink}
                         onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}>
-                        {this.props.StartLink ?
-                            <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
-                            : link}
+                        <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
                     </div>
                     : (null)
                 }
                 {
-                    this.props.InMenu ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
-                        <div className={'documentLinksButton' + (DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink) ? '-startLink' : ''} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }}>
-                            {this.props.StartLink ?
-                                <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
-                                : link}
+                    this.props.InMenu && this.props.StartLink ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+                        <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} onPointerDown={isActive ? undefined : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
+                            <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
                         </div>
-                        : (null)}
+                        :
+                        (null)
+                }
             </div>
         )
     }
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index ebdf030e7..ac6ec9b30 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -23,6 +23,7 @@
         .topBar-icon {
             cursor: pointer;
             font-size: 12px;
+            font-family: 'Roboto';
             width: fit-content;
             display: flex;
             justify-content: center;
@@ -91,7 +92,7 @@
             gap: 5px;
 
             .topBar-icon:hover {
-                background-color: $logout-red;
+                background-color: $close-red;
             }
 
             .topbar-lozenge-user,
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index bd9935333..05edb975c 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -12,7 +12,6 @@ import { Borders, Colors } from "../global/globalEnums";
 import "./TopBar.scss";
 
 /**
- * REACT TYPE: FUNCTIONAL
  * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user
  * and settings and help buttons. Future scope for this bar is to include the collaborators that are on the same Dashboard. 
  */
-- 
cgit v1.2.3-70-g09d2

