From 7e439440a1d7fc3e3b29333b0502d6ed4d178309 Mon Sep 17 00:00:00 2001
From: vkalev <vjk1883@gmail.com>
Date: Wed, 18 Aug 2021 12:12:23 -0400
Subject: highlighter tool added & working

---
 src/client/views/collections/CollectionMenu.tsx | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 8f4df4a92..835b3e575 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -614,12 +614,12 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
     private _dotsize = [10, 20, 30, 40];
-    private _draw = ["∿", "⎯", "→", "↔︎", "ロ", "O"];
-    private _head = ["", "", "", "arrow", "", ""];
-    private _end = ["", "", "arrow", "arrow", "", ""];
-    private _shapePrims = ["", "line", "line", "line", "rectangle", "circle"];
-    private _title = ["pen", "line", "line with arrow", "line with double arrows", "square", "circle",];
-    private _faName = ["pen-fancy", "minus", "long-arrow-alt-right", "arrows-alt-h", "square", "circle"];
+    private _draw = ["∿", "=", "⎯", "→", "↔︎", "ロ", "O"];
+    private _head = ["", "", "", "", "arrow", "", ""];
+    private _end = ["", "", "", "arrow", "arrow", "", ""];
+    private _shapePrims = ["", "", "line", "line", "line", "rectangle", "circle"];
+    private _title = ["pen", "highlighter", "line", "line with arrow", "line with double arrows", "square", "circle"];
+    private _faName = ["pen-fancy", "highlighter", "minus", "long-arrow-alt-right", "arrows-alt-h", "square", "circle"];
     @observable _selectedPrimitive = this._shapePrims.length;
     @observable _keepPrimitiveMode = false; // for whether primitive selection enters a one-shot or persistent mode
     @observable _colorBtn = false;
@@ -629,6 +629,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     @action clearKeepPrimitiveMode() { this._selectedPrimitive = this._shapePrims.length; }
     @action primCreated() {
         if (!this._keepPrimitiveMode) { //get out of ink mode after each stroke=
+            if (CurrentUserUtils.SelectedTool === InkTool.Highlighter && GestureOverlay.Instance.SavedColor) SetActiveInkColor(GestureOverlay.Instance.SavedColor);
             CurrentUserUtils.SelectedTool = InkTool.None;
             this._selectedPrimitive = this._shapePrims.length;
             SetActiveArrowStart("none");
@@ -669,7 +670,13 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
             this._keepPrimitiveMode = keep;
             if (this._selectedPrimitive !== i) {
                 this._selectedPrimitive = i;
-                CurrentUserUtils.SelectedTool = InkTool.Pen;
+                if (this._title[i] === "highlighter") {
+                    CurrentUserUtils.SelectedTool = InkTool.Highlighter;
+                    GestureOverlay.Instance.SavedColor = ActiveInkColor();
+                    SetActiveInkColor("rgba(245, 230, 95, 0.75)");
+                } else {
+                    CurrentUserUtils.SelectedTool = InkTool.Pen;
+                }
                 SetActiveArrowStart(this._head[i]);
                 SetActiveArrowEnd(this._end[i]);
                 SetActiveBezierApprox("300");
-- 
cgit v1.2.3-70-g09d2


From 917ebb4a7b6840f57abbf8dbcc197919f3ee3aac Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Wed, 18 Aug 2021 17:27:07 -0400
Subject: updates towards a menu

---
 src/client/documents/Documents.ts                  |    1 +
 src/client/util/CurrentUserUtils.ts                |    6 +-
 src/client/views/MainView.scss                     |    5 -
 src/client/views/MainView.tsx                      |    2 +
 src/client/views/StyleProvider.tsx                 |    3 +-
 src/client/views/collections/CollectionMenu.scss   | 1255 ++++++++++----------
 src/client/views/collections/CollectionMenu.tsx    |  101 +-
 .../collectionLinearView/CollectionLinearView.scss |   33 +-
 .../collectionLinearView/CollectionLinearView.tsx  |   43 +-
 src/client/views/nodes/DocumentView.tsx            |   29 +-
 src/client/views/nodes/button/FontIconBadge.tsx    |   13 +-
 src/client/views/nodes/button/FontIconBox.scss     |  262 ++--
 src/client/views/nodes/button/FontIconBox.tsx      |   81 +-
 13 files changed, 1022 insertions(+), 812 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 36cbd2059..817fbb9d6 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -227,6 +227,7 @@ export class DocumentOptions {
     //LINEAR VIEW
     linearViewIsExpanded?: boolean; // is linear view expanded
     linearViewExpandable?: boolean; // can linear view be expanded
+    linearViewToggleButton?: string; // button to open close linear view group
 
     layout_linkView?: Doc; // view template for a link document
     layout_keyValue?: string; // view tempalte for key value docs
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 620602070..cd4c217b5 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -547,7 +547,7 @@ export class CurrentUserUtils {
             { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
             { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
             { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
-            { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", 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: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
@@ -594,6 +594,7 @@ 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 }),
                 ignoreClick: true,
@@ -998,7 +999,7 @@ export class CurrentUserUtils {
                         onClick: click ? ScriptField.MakeScript(click, { scriptContext: "any" }) : undefined
                     }));
                 });
-                docList.push(CurrentUserUtils.blist({ ignoreClick: true, linearViewExpandable: true, _height: 30, backgroundColor: "transparent" }, textDocList));
+                docList.push(CurrentUserUtils.blist({ ignoreClick: true, linearViewExpandable: true, icon:"Text", _height: 30, backgroundColor: "transparent" }, textDocList));
             } else {
                 docList.push(Docs.Create.FontIconDocument({
                     _nativeWidth: width ? width : 30,
@@ -1197,6 +1198,7 @@ export class CurrentUserUtils {
         this.setupSearchSidebar(doc); // sets up the search sidebar
         this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
         this.setupOverlays(doc);  // documents in overlay layer
+        this.setupContextMenuButtons(doc); // set up context menu buttons
         this.setupDockedButtons(doc);  // the bottom bar of font icons
         await this.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels
         await this.setupMenuPanel(doc, sharingDocumentId, linkDatabaseId);
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index d913f2069..817e45699 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -265,11 +265,6 @@
         height: 35px;
         padding: 5px;
     }
-
-    svg {
-        width: 95% !important;
-        height: 95%;
-    }
 }
 
 .mainView-searchPanel {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6a388c5b4..5c1408148 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -439,6 +439,7 @@ export class MainView extends React.Component {
         this._flyoutWidth = (this._flyoutWidth || 250);
         this._sidebarContent.proto = button.target as any;
         this.LastButton = button;
+        console.log(button.title);
     });
 
     closeFlyout = action(() => {
@@ -446,6 +447,7 @@ export class MainView extends React.Component {
         this._panelContent = "none";
         this._sidebarContent.proto = undefined;
         this._flyoutWidth = 0;
+        console.log("close flyout");
     });
 
     remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index c9e532745..85520f6b3 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -96,6 +96,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             !Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
                 (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) : "author;creationDate") : "") || "";
         case StyleProp.Color:
+            if (MainView.Instance.LastButton === doc) return Colors.DARK_GRAY;
             const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color));
             if (docColor) return docColor;
             const backColor = backgroundCol();
@@ -114,8 +115,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) ||
             doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
         case StyleProp.BackgroundColor: {
+            if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
             let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : ""));
-            if (MainView.Instance.LastButton === doc) return darkScheme() ? Colors.MEDIUM_GRAY : Colors.LIGHT_GRAY;
             switch (doc?.type) {
                 case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
                 case DocumentType.PRES: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index f04b19ef7..163566d22 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -1,628 +1,659 @@
 @import "../global/globalCssVariables";
 
-.collectionMenu-cont {
-    position: relative;
-    display: inline-flex;
-    width: 100%;
-    opacity: 0.9;
-    z-index: 901;
-    transition: top .5s;
-    background: $dark-gray;
-    color: $white;
-    transform-origin: top left;
-    top: 0;
-    width: 100%;
-
-    .recordButtonOutline {
-        border-radius: 100%;
-        width: 18px;
-        height: 18px;
-        border: solid 1px $white;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-    }
-
-    .recordButtonInner {
-        border-radius: 100%;
-        width: 70%;
-        height: 70%;
-        background: $white;
-    }
-
-    .collectionMenu {
-        display: flex;
-        height: 100%;
-        overflow: visible;
-        z-index: 901;
-        border: unset;
-
-        .collectionMenu-divider {
-            height: 100%;
-            margin-left: 3px;
-            margin-right: 3px;
-            width: 2px;
-            background-color: $medium-gray;
-        }
-
-        .collectionViewBaseChrome {
-            display: flex;
-            align-items: center;
-
-            .collectionViewBaseChrome-viewPicker {
-                font-size: $small-text;
-                outline-color: $black;
-                color: $white;
-                border: none;
-                background: $dark-gray;               
-            }
-
-            .collectionViewBaseChrome-viewPicker:focus {
-                outline: none;
-                border: none;
-            }
-
-            .collectionViewBaseChrome-viewPicker:active {
-                outline-color: $black;
-            }
-
-            .collectionViewBaseChrome-button {
-                font-size: $small-text;
-                text-transform: uppercase;
-                letter-spacing: 2px;
-                background: $white;
-                color: $pink;
-                outline-color: $black;
-                border: none;
-                padding: 12px 10px 11px 10px;
-                margin-left: 10px;
-            }
-
-            .collectionViewBaseChrome-cmdPicker {
-                margin-left: 3px;
-                margin-right: 0px;
-                font-size: $small-text;
-                text-transform: capitalize;
-                color: $white;
-                border: none;
-                background: $dark-gray;     
-            }
-
-            .collectionViewBaseChrome-cmdPicker:focus {
-                border: none;
-                outline: none;
-            }
-
-            .commandEntry-outerDiv {
-                pointer-events: all;
-                background-color: transparent;
-                display: flex;
-                flex-direction: row;
-                align-items: center;
-                justify-content: center;
-                height: 100%;
-                overflow: hidden;
-
-                .commandEntry-drop {
-                    color: $white;
-                    width: 30px;
-                    margin-top: auto;
-                    margin-bottom: auto;
-                }
-            }
-
-            .commandEntry-outerDiv:hover{
-                background-color: $drop-shadow;
-
-                .collectionViewBaseChrome-viewPicker,
-                .collectionViewBaseChrome-cmdPicker{
-                    background: $dark-gray;
-                }
-            }
-
-            .collectionViewBaseChrome-collapse {
-                transition: all .5s, opacity 0.3s;
-                position: absolute;
-                width: 30px;
-                transform-origin: top left;
-                pointer-events: all;
-                // margin-top: 10px;
-            }
-
-            @media only screen and (max-device-width: 480px) {
-                .collectionViewBaseChrome-collapse {
-                    display: none;
-                }
-            }
-
-            .collectionViewBaseChrome-template,
-            .collectionViewBaseChrome-viewModes {
-                align-items: center;
-                height: 100%;
-                display: flex;
-                background: transparent;
-                color: $medium-gray;
-                justify-content: center;
-            }
-
-            .collectionViewBaseChrome-viewSpecs {
-                margin-left: 5px;
-                display: grid;
-                border: none;
-                border-right: solid $medium-gray 1px;
-
-                .collectionViewBaseChrome-filterIcon {
-                    position: relative;
-                    display: flex;
-                    margin: auto;
-                    background: $dark-gray;
-                    color: $white;
-                    width: 30px;
-                    height: 30px;
-                    align-items: center;
-                    justify-content: center;
-                    border: none;
-                    border-right: solid $medium-gray 1px;
-                }
-
-                .collectionViewBaseChrome-viewSpecsInput {
-                    padding: 12px 10px 11px 10px;
-                    border: 0px;
-                    color: $medium-gray;
-                    text-align: center;
-                    letter-spacing: 2px;
-                    outline-color: $black;
-                    font-size: $small-text;
-                    background: $white;
-                    height: 100%;
-                    width: 75px;
-                }
-
-                .collectionViewBaseChrome-viewSpecsMenu {
-                    overflow: hidden;
-                    transition: height .5s, display .5s;
-                    position: absolute;
-                    top: 60px;
-                    z-index: 100;
-                    display: flex;
-                    flex-direction: column;
-                    background: $white;
-                    box-shadow: $medium-gray 2px 2px 4px;
-
-                    .qs-datepicker {
-                        left: unset;
-                        right: 0;
-                    }
-
-                    .collectionViewBaseChrome-viewSpecsMenu-row {
-                        display: grid;
-                        grid-template-columns: 150px 200px 150px;
-                        margin-top: 10px;
-                        margin-right: 10px;
-
-                        .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
-                        .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
-                        .collectionViewBaseChrome-viewSpecsMenu-rowRight {
-                            font-size: $small-text;
-                            letter-spacing: 2px;
-                            color: $medium-gray;
-                            margin-left: 10px;
-                            padding: 5px;
-                            border: none;
-                            outline-color: $black;
-                        }
-                    }
-
-                    .collectionViewBaseChrome-viewSpecsMenu-lastRow {
-                        display: grid;
-                        grid-template-columns: 1fr 1fr 1fr;
-                        grid-gap: 10px;
-                        margin: 10px;
-                    }
-                }
-            }
-        }
-
-        .collectionStackingViewChrome-cont,
-        .collectionTreeViewChrome-cont,
-        .collection3DCarouselViewChrome-cont {
-            display: flex;
-            justify-content: space-between;
-        }
-
-        .collectionGridViewChrome-cont {
-            display: flex;
-            margin-left: 10;
-
-            .collectionGridViewChrome-viewPicker {
-                font-size: $small-text;
-                //text-transform: uppercase;
-                //letter-spacing: 2px;
-                background: $dark-gray;
-                color: $white;
-                outline-color: $black;
-                color: $white;
-                border: none;
-                border-right: solid $medium-gray 1px;
-            }
-
-            .collectionGridViewChrome-viewPicker:active {
-                outline-color: $black;
-            }
-
-            .grid-control {
-                align-self: center;
-                display: flex;
-                flex-direction: row;
-                margin-right: 5px;
-
-                .grid-icon {
-                    margin-right: 5px;
-                    align-self: center;
-                }
-
-                .flexLabel {
-                    margin-bottom: 0;
-                }
-
-                .collectionGridViewChrome-entryBox {
-                    width: 50%;
-                    color: $black;
-                }
-
-                .collectionGridViewChrome-columnButton {
-                    color: $black;
-                }
-            }
-        }
-
-        .collectionStackingViewChrome-sort,
-        .collectionTreeViewChrome-sort {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-
-            .collectionStackingViewChrome-sortIcon,
-            .collectionTreeViewChrome-sortIcon {
-                transition: transform .5s;
-                margin-left: 10px;
-            }
-        }
-
-        button:hover {
-            transform: scale(1);
-        }
-
-
-        .collectionStackingViewChrome-pivotField-cont,
-        .collectionTreeViewChrome-pivotField-cont,
-        .collection3DCarouselViewChrome-scrollSpeed-cont {
-            justify-self: right;
-            align-items: center;
-            display: flex;
-            grid-auto-columns: auto;
-            font-size: $small-text;
-            letter-spacing: 2px;
-
-            .collectionStackingViewChrome-pivotField-label,
-            .collectionTreeViewChrome-pivotField-label,
-            .collection3DCarouselViewChrome-scrollSpeed-label {
-                grid-column: 1;
-                margin-right: 7px;
-                user-select: none;
-                font-family: $sans-serif;
-                letter-spacing: normal;
-            }
-
-            .collectionStackingViewChrome-sortIcon {
-                transition: transform .5s;
-                grid-column: 3;
-                text-align: center;
-                display: flex;
-                justify-content: center;
-                align-items: center;
-                cursor: pointer;
-                width: 25px;
-                height: 25px;
-                border-radius: 100%;
-            }
-
-            .collectionStackingViewChrome-sortIcon:hover {
-                background-color: $drop-shadow;
-            }
-
-            .collectionStackingViewChrome-pivotField,
-            .collectionTreeViewChrome-pivotField,
-            .collection3DCarouselViewChrome-scrollSpeed {
-                color: $white;
-                grid-column: 2;
-                grid-row: 1;
-                width: 90%;
-                min-width: 100px;
-                display: flex;
-                height: 80%;
-                border-radius: 7px;
-                align-items: center;
-                background: $white;
-
-                .editable-view-input,
-                input,
-                .editableView-container-editing-oneLine,
-                .editableView-container-editing {
-                    margin: auto;
-                    border: 0px;
-                    color: $light-gray !important;
-                    text-align: center;
-                    letter-spacing: 2px;
-                    outline-color: $black;
-                    height: 100%;
-                }
-
-                .react-autosuggest__container {
-                    margin: 0;
-                    color: $medium-gray;
-                    padding: 0px;
-                }
-            }
-        }
-
-        .collectionStackingViewChrome-pivotField:hover,
-        .collectionTreeViewChrome-pivotField:hover,
-        .collection3DCarouselViewChrome-scrollSpeed:hover {
-            cursor: text;
-        }
-
-    }
-}
-
-.collectionMenu-webUrlButtons {
-    margin-left: 44;
-    background: lightGray;
+.collectionMenu-container {
     display: flex;
-}
-
-.webBox-urlEditor {
-    position: relative;
-    opacity: 0.9;
-    z-index: 901;
-    transition: top .5s;
-
-    .urlEditor {
-        display: grid;
-        grid-template-columns: 1fr auto;
-        padding-bottom: 10px;
-        overflow: hidden;
-        margin-top: 5px;
-        height: 35px;
-
-        .editorBase {
-            display: flex;
-
-            .editor-collapse {
-                transition: all .5s, opacity 0.3s;
-                position: absolute;
-                width: 40px;
-                transform-origin: top left;
-            }
-
-            .switchToText {
-                color: $medium-gray;
-            }
-
-            .switchToText:hover {
-                color: $dark-gray;
-            }
-        }
-
-        button:hover {
-            transform: scale(1);
-        }
-    }
-}
-
-.collectionMenu-urlInput {
-    padding: 12px 10px 11px 10px;
-    border: 0px;
-    color: $black;
-    font-size: $small-text;
-    letter-spacing: 2px;
-    outline-color: $black;
-    background: $white;
-    width: 100%;
-    min-width: 350px;
-    margin-right: 10px;
-    height: 100%;
-}
-
-.collectionFreeFormMenu-cont {
-    display: inline-flex;
     position: relative;
+    align-content: center;
+    justify-content: space-between;
+    background-color: $dark-gray;
+    height: 35px;
+    border-bottom: $standard-border;
+    padding-right: 5px;
     align-items: center;
-    height: 100%;
-
-    .color-previewI {
-        width: 60%;
-        top: 80%;
-        position: absolute;
-        height: 4px;
-    }
-
-    .color-previewII {
-        width: 80%;
-        height: 80%;
-        margin-left: 10%;
-        position: absolute;
-        bottom: 5;
-    }
-
-    .btn-group {
-        display: grid;
-        grid-template-columns: auto auto auto auto;
-        margin: auto;
-        /* Make the buttons appear below each other */
-    }
 
-    .btn-draw {
-        display: inline-flex;
-        margin: auto;
-        /* Make the buttons appear below each other */
-    }
-
-    .fwdKeyframe,
-    .numKeyframe,
-    .backKeyframe {
+    .collectionMenu-hardCodedButton {
         cursor: pointer;
-        position: relative;
-        width: 20;
-        height: 30;
-        bottom: 0;
-        background: $dark-gray;
-        display: inline-flex;
-        align-items: center;
         color: $white;
-    }
-
-    .backKeyframe {
-        svg {
-            display: block;
-            margin: auto;
-        }
-    }
-
-
-    .numKeyframe {
-        flex-direction: column;
-        padding-top: 5px;
-    }
-
-    .fwdKeyframe {
-        svg {
-            display: block;
-            margin: auto;
-        }
-
-        border-right: solid $medium-gray 1px;
-    }
-}
-
-.collectionSchemaViewChrome-cont {
-    display: flex;
-    font-size: $small-text;
-
-    .collectionSchemaViewChrome-toggle {
-        display: flex;
-        margin-left: 10px;
-    }
-
-    .collectionSchemaViewChrome-label {
-        text-transform: uppercase;
-        letter-spacing: 2px;
-        margin-right: 5px;
+        width: 31.5px;
+        height: 90%;
+        padding: 5;
+        text-align: center;
         display: flex;
-        flex-direction: column;
         justify-content: center;
-    }
-
-    .collectionSchemaViewChrome-toggler {
-        width: 100px;
-        height: 35px;
-        background-color: $black;
+        align-items: center;
         position: relative;
-    }
-
-    .collectionSchemaViewChrome-togglerButton {
-        width: 47px;
-        height: 30px;
-        background-color: $light-gray;
-        // position: absolute;
-        transition: all 0.5s ease;
-        // top: 3px;
-        margin-top: 3px;
-        color: $medium-gray;
-        letter-spacing: 2px;
-        text-transform: uppercase;
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        text-align: center;
+        transition: 0.2s;
 
-        &.on {
-            margin-left: 3px;
-        }
-
-        &.off {
-            margin-left: 50px;
+        &:hover {
+            border-radius:5px;
+            background-color: rgba(0,0,0,0.2);
         }
     }
 }
 
-
-.commandEntry-outerDiv {
-    display: flex;
-    flex-direction: column;
-    height: 40px;
-}
-
-.commandEntry-inputArea {
-    display: flex;
-    flex-direction: row;
-    width: 150px;
-    margin: auto auto auto auto;
-}
-
-.react-autosuggest__container {
-    position: relative;
-    width: 100%;
-    margin-left: 5px;
-    margin-right: 5px;
-}
-
-.react-autosuggest__input {
-    border: 1px solid $light-gray;
-    border-radius: 4px;
-    width: 100%;
-}
-
-.react-autosuggest__input--focused {
-    outline: none;
-}
-
-.react-autosuggest__input--open {
-    border-bottom-left-radius: 0;
-    border-bottom-right-radius: 0;
-}
-
-.react-autosuggest__suggestions-container {
-    display: none;
-}
-
-.react-autosuggest__suggestions-container--open {
-    display: block;
-    position: fixed;
-    overflow-y: auto;
-    max-height: 400px;
-    width: 180px;
-    border: 1px solid $light-gray;
-    background-color: $white;
-    font-family: $sans-serif;
-    font-weight: 300;
-    font-size: $large-header;
-    border-bottom-left-radius: 4px;
-    border-bottom-right-radius: 4px;
-    z-index: 2;
-}
-
-.react-autosuggest__suggestions-list {
-    margin: 0;
-    padding: 0;
-    list-style-type: none;
-}
-
-.react-autosuggest__suggestion {
-    cursor: pointer;
-    padding: 10px 20px;
-}
-
-.react-autosuggest__suggestion--highlighted {
-    background-color: $light-gray;
-}
\ No newline at end of file
+// .collectionMenu-cont {
+//     position: relative;
+//     display: inline-flex;
+//     width: 100%;
+//     opacity: 0.9;
+//     z-index: 901;
+//     transition: top .5s;
+//     background: $dark-gray;
+//     color: $white;
+//     transform-origin: top left;
+//     top: 0;
+//     width: 100%;
+
+//     .recordButtonOutline {
+//         border-radius: 100%;
+//         width: 18px;
+//         height: 18px;
+//         border: solid 1px $white;
+//         display: flex;
+//         align-items: center;
+//         justify-content: center;
+//     }
+
+//     .recordButtonInner {
+//         border-radius: 100%;
+//         width: 70%;
+//         height: 70%;
+//         background: $white;
+//     }
+
+//     .collectionMenu {
+//         display: flex;
+//         height: 100%;
+//         overflow: visible;
+//         z-index: 901;
+//         border: unset;
+
+//         .collectionMenu-divider {
+//             height: 100%;
+//             margin-left: 3px;
+//             margin-right: 3px;
+//             width: 2px;
+//             background-color: $medium-gray;
+//         }
+
+//         .collectionViewBaseChrome {
+//             display: flex;
+//             align-items: center;
+
+//             .collectionViewBaseChrome-viewPicker {
+//                 font-size: $small-text;
+//                 outline-color: $black;
+//                 color: $white;
+//                 border: none;
+//                 background: $dark-gray;               
+//             }
+
+//             .collectionViewBaseChrome-viewPicker:focus {
+//                 outline: none;
+//                 border: none;
+//             }
+
+//             .collectionViewBaseChrome-viewPicker:active {
+//                 outline-color: $black;
+//             }
+
+//             .collectionViewBaseChrome-button {
+//                 font-size: $small-text;
+//                 text-transform: uppercase;
+//                 letter-spacing: 2px;
+//                 background: $white;
+//                 color: $pink;
+//                 outline-color: $black;
+//                 border: none;
+//                 padding: 12px 10px 11px 10px;
+//                 margin-left: 10px;
+//             }
+
+//             .collectionViewBaseChrome-cmdPicker {
+//                 margin-left: 3px;
+//                 margin-right: 0px;
+//                 font-size: $small-text;
+//                 text-transform: capitalize;
+//                 color: $white;
+//                 border: none;
+//                 background: $dark-gray;     
+//             }
+
+//             .collectionViewBaseChrome-cmdPicker:focus {
+//                 border: none;
+//                 outline: none;
+//             }
+
+//             .commandEntry-outerDiv {
+//                 pointer-events: all;
+//                 background-color: transparent;
+//                 display: flex;
+//                 flex-direction: row;
+//                 align-items: center;
+//                 justify-content: center;
+//                 height: 100%;
+//                 overflow: hidden;
+
+//                 .commandEntry-drop {
+//                     color: $white;
+//                     width: 30px;
+//                     margin-top: auto;
+//                     margin-bottom: auto;
+//                 }
+//             }
+
+//             .commandEntry-outerDiv:hover{
+//                 background-color: $drop-shadow;
+
+//                 .collectionViewBaseChrome-viewPicker,
+//                 .collectionViewBaseChrome-cmdPicker{
+//                     background: $dark-gray;
+//                 }
+//             }
+
+//             .collectionViewBaseChrome-collapse {
+//                 transition: all .5s, opacity 0.3s;
+//                 position: absolute;
+//                 width: 30px;
+//                 transform-origin: top left;
+//                 pointer-events: all;
+//                 // margin-top: 10px;
+//             }
+
+//             @media only screen and (max-device-width: 480px) {
+//                 .collectionViewBaseChrome-collapse {
+//                     display: none;
+//                 }
+//             }
+
+//             .collectionViewBaseChrome-template,
+//             .collectionViewBaseChrome-viewModes {
+//                 align-items: center;
+//                 height: 100%;
+//                 display: flex;
+//                 background: transparent;
+//                 color: $medium-gray;
+//                 justify-content: center;
+//             }
+
+//             .collectionViewBaseChrome-viewSpecs {
+//                 margin-left: 5px;
+//                 display: grid;
+//                 border: none;
+//                 border-right: solid $medium-gray 1px;
+
+//                 .collectionViewBaseChrome-filterIcon {
+//                     position: relative;
+//                     display: flex;
+//                     margin: auto;
+//                     background: $dark-gray;
+//                     color: $white;
+//                     width: 30px;
+//                     height: 30px;
+//                     align-items: center;
+//                     justify-content: center;
+//                     border: none;
+//                     border-right: solid $medium-gray 1px;
+//                 }
+
+//                 .collectionViewBaseChrome-viewSpecsInput {
+//                     padding: 12px 10px 11px 10px;
+//                     border: 0px;
+//                     color: $medium-gray;
+//                     text-align: center;
+//                     letter-spacing: 2px;
+//                     outline-color: $black;
+//                     font-size: $small-text;
+//                     background: $white;
+//                     height: 100%;
+//                     width: 75px;
+//                 }
+
+//                 .collectionViewBaseChrome-viewSpecsMenu {
+//                     overflow: hidden;
+//                     transition: height .5s, display .5s;
+//                     position: absolute;
+//                     top: 60px;
+//                     z-index: 100;
+//                     display: flex;
+//                     flex-direction: column;
+//                     background: $white;
+//                     box-shadow: $medium-gray 2px 2px 4px;
+
+//                     .qs-datepicker {
+//                         left: unset;
+//                         right: 0;
+//                     }
+
+//                     .collectionViewBaseChrome-viewSpecsMenu-row {
+//                         display: grid;
+//                         grid-template-columns: 150px 200px 150px;
+//                         margin-top: 10px;
+//                         margin-right: 10px;
+
+//                         .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
+//                         .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
+//                         .collectionViewBaseChrome-viewSpecsMenu-rowRight {
+//                             font-size: $small-text;
+//                             letter-spacing: 2px;
+//                             color: $medium-gray;
+//                             margin-left: 10px;
+//                             padding: 5px;
+//                             border: none;
+//                             outline-color: $black;
+//                         }
+//                     }
+
+//                     .collectionViewBaseChrome-viewSpecsMenu-lastRow {
+//                         display: grid;
+//                         grid-template-columns: 1fr 1fr 1fr;
+//                         grid-gap: 10px;
+//                         margin: 10px;
+//                     }
+//                 }
+//             }
+//         }
+
+//         .collectionStackingViewChrome-cont,
+//         .collectionTreeViewChrome-cont,
+//         .collection3DCarouselViewChrome-cont {
+//             display: flex;
+//             justify-content: space-between;
+//         }
+
+//         .collectionGridViewChrome-cont {
+//             display: flex;
+//             margin-left: 10;
+
+//             .collectionGridViewChrome-viewPicker {
+//                 font-size: $small-text;
+//                 //text-transform: uppercase;
+//                 //letter-spacing: 2px;
+//                 background: $dark-gray;
+//                 color: $white;
+//                 outline-color: $black;
+//                 color: $white;
+//                 border: none;
+//                 border-right: solid $medium-gray 1px;
+//             }
+
+//             .collectionGridViewChrome-viewPicker:active {
+//                 outline-color: $black;
+//             }
+
+//             .grid-control {
+//                 align-self: center;
+//                 display: flex;
+//                 flex-direction: row;
+//                 margin-right: 5px;
+
+//                 .grid-icon {
+//                     margin-right: 5px;
+//                     align-self: center;
+//                 }
+
+//                 .flexLabel {
+//                     margin-bottom: 0;
+//                 }
+
+//                 .collectionGridViewChrome-entryBox {
+//                     width: 50%;
+//                     color: $black;
+//                 }
+
+//                 .collectionGridViewChrome-columnButton {
+//                     color: $black;
+//                 }
+//             }
+//         }
+
+//         .collectionStackingViewChrome-sort,
+//         .collectionTreeViewChrome-sort {
+//             display: flex;
+//             align-items: center;
+//             justify-content: space-between;
+
+//             .collectionStackingViewChrome-sortIcon,
+//             .collectionTreeViewChrome-sortIcon {
+//                 transition: transform .5s;
+//                 margin-left: 10px;
+//             }
+//         }
+
+//         button:hover {
+//             transform: scale(1);
+//         }
+
+
+//         .collectionStackingViewChrome-pivotField-cont,
+//         .collectionTreeViewChrome-pivotField-cont,
+//         .collection3DCarouselViewChrome-scrollSpeed-cont {
+//             justify-self: right;
+//             align-items: center;
+//             display: flex;
+//             grid-auto-columns: auto;
+//             font-size: $small-text;
+//             letter-spacing: 2px;
+
+//             .collectionStackingViewChrome-pivotField-label,
+//             .collectionTreeViewChrome-pivotField-label,
+//             .collection3DCarouselViewChrome-scrollSpeed-label {
+//                 grid-column: 1;
+//                 margin-right: 7px;
+//                 user-select: none;
+//                 font-family: $sans-serif;
+//                 letter-spacing: normal;
+//             }
+
+//             .collectionStackingViewChrome-sortIcon {
+//                 transition: transform .5s;
+//                 grid-column: 3;
+//                 text-align: center;
+//                 display: flex;
+//                 justify-content: center;
+//                 align-items: center;
+//                 cursor: pointer;
+//                 width: 25px;
+//                 height: 25px;
+//                 border-radius: 100%;
+//             }
+
+//             .collectionStackingViewChrome-sortIcon:hover {
+//                 background-color: $drop-shadow;
+//             }
+
+//             .collectionStackingViewChrome-pivotField,
+//             .collectionTreeViewChrome-pivotField,
+//             .collection3DCarouselViewChrome-scrollSpeed {
+//                 color: $white;
+//                 grid-column: 2;
+//                 grid-row: 1;
+//                 width: 90%;
+//                 min-width: 100px;
+//                 display: flex;
+//                 height: 80%;
+//                 border-radius: 7px;
+//                 align-items: center;
+//                 background: $white;
+
+//                 .editable-view-input,
+//                 input,
+//                 .editableView-container-editing-oneLine,
+//                 .editableView-container-editing {
+//                     margin: auto;
+//                     border: 0px;
+//                     color: $light-gray !important;
+//                     text-align: center;
+//                     letter-spacing: 2px;
+//                     outline-color: $black;
+//                     height: 100%;
+//                 }
+
+//                 .react-autosuggest__container {
+//                     margin: 0;
+//                     color: $medium-gray;
+//                     padding: 0px;
+//                 }
+//             }
+//         }
+
+//         .collectionStackingViewChrome-pivotField:hover,
+//         .collectionTreeViewChrome-pivotField:hover,
+//         .collection3DCarouselViewChrome-scrollSpeed:hover {
+//             cursor: text;
+//         }
+
+//     }
+// }
+
+// .collectionMenu-webUrlButtons {
+//     margin-left: 44;
+//     background: lightGray;
+//     display: flex;
+// }
+
+// .webBox-urlEditor {
+//     position: relative;
+//     opacity: 0.9;
+//     z-index: 901;
+//     transition: top .5s;
+
+//     .urlEditor {
+//         display: grid;
+//         grid-template-columns: 1fr auto;
+//         padding-bottom: 10px;
+//         overflow: hidden;
+//         margin-top: 5px;
+//         height: 35px;
+
+//         .editorBase {
+//             display: flex;
+
+//             .editor-collapse {
+//                 transition: all .5s, opacity 0.3s;
+//                 position: absolute;
+//                 width: 40px;
+//                 transform-origin: top left;
+//             }
+
+//             .switchToText {
+//                 color: $medium-gray;
+//             }
+
+//             .switchToText:hover {
+//                 color: $dark-gray;
+//             }
+//         }
+
+//         button:hover {
+//             transform: scale(1);
+//         }
+//     }
+// }
+
+// .collectionMenu-urlInput {
+//     padding: 12px 10px 11px 10px;
+//     border: 0px;
+//     color: $black;
+//     font-size: $small-text;
+//     letter-spacing: 2px;
+//     outline-color: $black;
+//     background: $white;
+//     width: 100%;
+//     min-width: 350px;
+//     margin-right: 10px;
+//     height: 100%;
+// }
+
+// .collectionFreeFormMenu-cont {
+//     display: inline-flex;
+//     position: relative;
+//     align-items: center;
+//     height: 100%;
+
+//     .color-previewI {
+//         width: 60%;
+//         top: 80%;
+//         position: absolute;
+//         height: 4px;
+//     }
+
+//     .color-previewII {
+//         width: 80%;
+//         height: 80%;
+//         margin-left: 10%;
+//         position: absolute;
+//         bottom: 5;
+//     }
+
+//     .btn-group {
+//         display: grid;
+//         grid-template-columns: auto auto auto auto;
+//         margin: auto;
+//         /* Make the buttons appear below each other */
+//     }
+
+//     .btn-draw {
+//         display: inline-flex;
+//         margin: auto;
+//         /* Make the buttons appear below each other */
+//     }
+
+//     .fwdKeyframe,
+//     .numKeyframe,
+//     .backKeyframe {
+//         cursor: pointer;
+//         position: relative;
+//         width: 20;
+//         height: 30;
+//         bottom: 0;
+//         background: $dark-gray;
+//         display: inline-flex;
+//         align-items: center;
+//         color: $white;
+//     }
+
+//     .backKeyframe {
+//         svg {
+//             display: block;
+//             margin: auto;
+//         }
+//     }
+
+
+//     .numKeyframe {
+//         flex-direction: column;
+//         padding-top: 5px;
+//     }
+
+//     .fwdKeyframe {
+//         svg {
+//             display: block;
+//             margin: auto;
+//         }
+
+//         border-right: solid $medium-gray 1px;
+//     }
+// }
+
+// .collectionSchemaViewChrome-cont {
+//     display: flex;
+//     font-size: $small-text;
+
+//     .collectionSchemaViewChrome-toggle {
+//         display: flex;
+//         margin-left: 10px;
+//     }
+
+//     .collectionSchemaViewChrome-label {
+//         text-transform: uppercase;
+//         letter-spacing: 2px;
+//         margin-right: 5px;
+//         display: flex;
+//         flex-direction: column;
+//         justify-content: center;
+//     }
+
+//     .collectionSchemaViewChrome-toggler {
+//         width: 100px;
+//         height: 35px;
+//         background-color: $black;
+//         position: relative;
+//     }
+
+//     .collectionSchemaViewChrome-togglerButton {
+//         width: 47px;
+//         height: 30px;
+//         background-color: $light-gray;
+//         // position: absolute;
+//         transition: all 0.5s ease;
+//         // top: 3px;
+//         margin-top: 3px;
+//         color: $medium-gray;
+//         letter-spacing: 2px;
+//         text-transform: uppercase;
+//         display: flex;
+//         flex-direction: column;
+//         justify-content: center;
+//         text-align: center;
+
+//         &.on {
+//             margin-left: 3px;
+//         }
+
+//         &.off {
+//             margin-left: 50px;
+//         }
+//     }
+// }
+
+
+// .commandEntry-outerDiv {
+//     display: flex;
+//     flex-direction: column;
+//     height: 40px;
+// }
+
+// .commandEntry-inputArea {
+//     display: flex;
+//     flex-direction: row;
+//     width: 150px;
+//     margin: auto auto auto auto;
+// }
+
+// .react-autosuggest__container {
+//     position: relative;
+//     width: 100%;
+//     margin-left: 5px;
+//     margin-right: 5px;
+// }
+
+// .react-autosuggest__input {
+//     border: 1px solid $light-gray;
+//     border-radius: 4px;
+//     width: 100%;
+// }
+
+// .react-autosuggest__input--focused {
+//     outline: none;
+// }
+
+// .react-autosuggest__input--open {
+//     border-bottom-left-radius: 0;
+//     border-bottom-right-radius: 0;
+// }
+
+// .react-autosuggest__suggestions-container {
+//     display: none;
+// }
+
+// .react-autosuggest__suggestions-container--open {
+//     display: block;
+//     position: fixed;
+//     overflow-y: auto;
+//     max-height: 400px;
+//     width: 180px;
+//     border: 1px solid $light-gray;
+//     background-color: $white;
+//     font-family: $sans-serif;
+//     font-weight: 300;
+//     font-size: $large-header;
+//     border-bottom-left-radius: 4px;
+//     border-bottom-right-radius: 4px;
+//     z-index: 2;
+// }
+
+// .react-autosuggest__suggestions-list {
+//     margin: 0;
+//     padding: 0;
+//     list-style-type: none;
+// }
+
+// .react-autosuggest__suggestion {
+//     cursor: pointer;
+//     padding: 10px 20px;
+// }
+
+// .react-autosuggest__suggestion--highlighted {
+//     background-color: $light-gray;
+// }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 8f4df4a92..55af4650f 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -15,29 +15,31 @@ import { RichTextField } from "../../../fields/RichTextField";
 import { listSpec } from "../../../fields/Schema";
 import { ScriptField } from "../../../fields/ScriptField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils";
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 import { DragManager } from "../../util/DragManager";
 import { Scripting } from "../../util/Scripting";
 import { SelectionManager } from "../../util/SelectionManager";
+import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu";
 import { EditableView } from "../EditableView";
 import { GestureOverlay } from "../GestureOverlay";
-import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth, ActiveArrowStart, ActiveArrowEnd } from "../InkingStroke";
+import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "../InkingStroke";
+import { LightboxView } from "../LightboxView";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocumentView } from "../nodes/DocumentView";
+import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
 import { RichTextMenu } from "../nodes/formattedText/RichTextMenu";
 import { PresBox } from "../nodes/trails/PresBox";
+import { DefaultStyleProvider } from "../StyleProvider";
+import { CollectionDockingView } from "./CollectionDockingView";
+import { CollectionLinearView } from "./CollectionLinearView";
 import "./CollectionMenu.scss";
 import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
-import { LightboxView } from "../LightboxView";
-import { Docs } from "../../documents/Documents";
-import { DocumentManager } from "../../util/DocumentManager";
-import { CollectionDockingView } from "./CollectionDockingView";
-import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
 
 @observer
 export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -46,6 +48,8 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
     @observable SelectedCollection: DocumentView | undefined;
     @observable FieldKey: string;
 
+    private _docBtnRef = React.createRef<HTMLDivElement>();
+
     constructor(props: any) {
         super(props);
         this.FieldKey = "";
@@ -82,30 +86,85 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
         }
     }
 
+    buttonBarXf = () => {
+        if (!this._docBtnRef.current) return Transform.Identity();
+        const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current);
+        return new Transform(-translateX, -translateY, 1 / scale);
+    }
+
+    @computed get contMenuButtons() {
+        const selDoc = Doc.UserDoc().contextMenuBtns;
+        return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: "35px" }} >
+            <CollectionLinearView
+                Document={selDoc}
+                DataDoc={undefined}
+                fieldKey={"data"}
+                dropAction={"alias"}
+                setHeight={returnFalse}
+                styleProvider={DefaultStyleProvider}
+                layerProvider={undefined}
+                rootSelected={returnTrue}
+                bringToFront={emptyFunction}
+                select={emptyFunction}
+                isContentActive={returnFalse}
+                isSelected={returnFalse}
+                docViewPath={returnEmptyDoclist}
+                moveDocument={returnFalse}
+                CollectionView={undefined}
+                addDocument={returnFalse}
+                addDocTab={returnFalse}
+                pinToPres={emptyFunction}
+                removeDocument={returnFalse}
+                ScreenToLocalTransform={this.buttonBarXf}
+                PanelWidth={() => 100}
+                PanelHeight={() => 35}
+                renderDepth={0}
+                focus={() => undefined}
+                whenChildContentsActiveChanged={emptyFunction}
+                docFilters={returnEmptyFilter}
+                docRangeFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
+                ContainingCollectionView={undefined}
+                ContainingCollectionDoc={undefined} />
+        </div>;
+    }
+
     render() {
-        const button = <Tooltip title={<div className="dash-tooltip">Pin Menu</div>} key="pin menu" placement="bottom">
-            <button className="antimodeMenu-button" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
-                <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
-            </button>
-        </Tooltip>;
 
         const propIcon = CurrentUserUtils.propertiesWidth > 0 ? "angle-double-right" : "angle-double-left";
         const propTitle = CurrentUserUtils.propertiesWidth > 0 ? "Close Properties Panel" : "Open Properties Panel";
 
         const prop = <Tooltip title={<div className="dash-tooltip">{propTitle}</div>} key="properties" placement="bottom">
-            <button className="antimodeMenu-button" key="properties" style={{ backgroundColor: "#424242" }}
+            <div className="collectionMenu-hardCodedButton" key="properties"
                 onPointerDown={this.toggleProperties}>
                 <FontAwesomeIcon icon={propIcon} size="lg" />
-            </button>
+            </div>
         </Tooltip>;
 
-        return this.getElement(!this.SelectedCollection ? [/*button*/] :
-            [<CollectionViewBaseChrome key="chrome"
-                docView={this.SelectedCollection}
-                fieldKey={this.SelectedCollection.LayoutFieldKey}
-                type={StrCast(this.SelectedCollection?.props.Document._viewType, CollectionViewType.Invalid) as CollectionViewType} />,
-                prop,
-                /*button*/]);
+        // NEW BUTTONS
+        //dash col linear view buttons
+        const contMenuButtons = 
+        <div className="collectionMenu-container">
+            {this.contMenuButtons}
+            {prop}
+        </div>;
+
+        return contMenuButtons;
+
+        // const button = <Tooltip title={<div className="dash-tooltip">Pin Menu</div>} key="pin menu" placement="bottom">
+        //     <button className="antimodeMenu-button" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
+        //         <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
+        //     </button>
+        // </Tooltip>;
+
+        // OLD BUTTONS
+        // return this.getElement(!this.SelectedCollection ? [/*button*/] :
+        //     [<CollectionViewBaseChrome key="chrome"
+        //         docView={this.SelectedCollection}
+        //         fieldKey={this.SelectedCollection.LayoutFieldKey}
+        //         type={StrCast(this.SelectedCollection?.props.Document._viewType, CollectionViewType.Invalid) as CollectionViewType} />,
+        //         prop,
+        //         /*button*/]);
     }
 }
 
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
index a10d43917..db39e304b 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
@@ -5,12 +5,22 @@
     overflow: visible;
     height: 100%;
     pointer-events: none;
+    // background-color: rgba(0, 0, 0, 0.2);
+    border-radius: 5px;
+    padding-left: 5px;
+    padding-right: 5px;
+    border-left: $standard-border;
+    border-right: $standard-border;
 
     .collectionLinearView {
         display: flex;
         height: 100%;
         align-items: center;
 
+        .collectionView{
+            overflow: visible !important;
+        }
+
         >span {
             background: $dark-gray;
             color: $white;
@@ -67,29 +77,25 @@
         }
 
         >label {
-            margin-top: "auto";
-            margin-bottom: "auto";
             background: $dark-gray;
             color: $white;
-            display: inline-block;
+            display: flex;
             border-radius: 18px;
             font-size: 12.5px;
-            width: 18px;
-            height: 18px;
+            font-weight:100;
+            width: fit-content;
+            height: 100%;
             margin-top: auto;
             margin-bottom: auto;
             margin-right: 3px;
             cursor: pointer;
             transition: transform 0.2s;
-        }
-
-        label p {
-            padding-left: 5px;
-        }
+            align-items: center;
+            justify-content: center;
 
-        label:hover {
-            background: $medium-gray;
-            transform: scale(1.15);
+            &:hover {
+                background: $medium-gray;
+            }
         }
 
         >input {
@@ -110,7 +116,6 @@
             display: flex;
             opacity: 1;
             position: relative;
-            margin-top: auto;
 
             .collectionLinearView-docBtn,
             .collectionLinearView-docBtn-scalable {
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
index 8e2ba2275..e7970758a 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
@@ -2,20 +2,21 @@ import { Tooltip } from '@material-ui/core';
 import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { makeInterface } from '../../../../fields/Schema';
+import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
 import { documentSchema } from '../../../../fields/documentSchemas';
-import { CollectionSubView } from '../CollectionSubView';
+import { Id } from '../../../../fields/FieldSymbols';
+import { makeInterface } from '../../../../fields/Schema';
+import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils';
 import { DragManager } from '../../../util/DragManager';
-import { ScriptCast, NumCast, StrCast, BoolCast } from '../../../../fields/Types';
-import { HeightSym, Doc, WidthSym } from '../../../../fields/Doc';
-import { Utils, returnFalse, returnTrue, emptyFunction, returnEmptyDoclist } from '../../../../Utils';
+import { Transform } from '../../../util/Transform';
 import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
+import { DocumentView } from '../../nodes/DocumentView';
 import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
 import { StyleProp } from '../../StyleProvider';
-import { CollectionViewType } from '../CollectionView';
-import { Id } from '../../../../fields/FieldSymbols';
-import { DocumentView } from '../../nodes/DocumentView';
-import { Transform } from '../../../util/Transform';
+import "./CollectionLinearView.scss";
+import { CollectionSubView } from '.././CollectionSubView';
+import { CollectionViewType } from '.././CollectionView';
 
 
 type LinearDocument = makeInterface<[typeof documentSchema,]>;
@@ -108,33 +109,37 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
     render() {
         const guid = Utils.GenerateGuid();
         const flexDir: any = StrCast(this.Document.flexDirection);
+        const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable);
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const icon: string = StrCast(this.props.Document.icon);
 
         const menuOpener = <label htmlFor={`${guid}`} style={{ pointerEvents: "all", cursor: "pointer", background: backgroundColor === color ? "black" : backgroundColor, }}
             onPointerDown={e => e.stopPropagation()} >
-            <p>{BoolCast(this.layoutDoc.linearViewIsExpanded) ? "–" : "+"}</p>
+            <p>{BoolCast(this.layoutDoc.linearViewIsExpanded) ? icon ? icon : "–" : icon ? icon : "+"}</p>
         </label>;
 
         return <div className="collectionLinearView-outer">
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
-                <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.layoutDoc.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top">
+                {!expandable ? (null) : <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top">
                     {menuOpener}
-                </Tooltip>
-                <input id={`${guid}`} type="checkbox" checked={BoolCast(this.layoutDoc.linearViewIsExpanded)} ref={this.addMenuToggle}
-                    onChange={action(() => this.layoutDoc.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
+                </Tooltip>}
+                <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
+                    onChange={action(() => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
 
                 <div className="collectionLinearView-content" style={{ height: this.dimension(), flexDirection: flexDir }}>
                     {this.childLayoutPairs.map((pair, ind) => {
                         const nested = pair.layout._viewType === CollectionViewType.Linear;
                         const dref = React.createRef<HTMLDivElement>();
-                        const scalable = pair.layout.onClick || pair.layout.onDragStart;
-                        return <div className={`collectionLinearView-docBtn` + (scalable ? "-scalable" : "")} key={pair.layout[Id]} ref={dref}
+                        // const scalable = pair.layout.onClick || pair.layout.onDragStart;
+                        console.log("Height:" + NumCast(pair.layout._height));
+                        return <div className={`collectionLinearView-docBtn`} key={pair.layout[Id]} ref={dref}
                             style={{
                                 pointerEvents: "all",
-                                minWidth: 30,
-                                width: nested ? pair.layout[WidthSym]() : this.dimension(),
-                                height: nested && pair.layout.linearViewIsExpanded ? pair.layout[HeightSym]() : this.dimension(),
+                                width: nested ? undefined : NumCast(pair.layout._width),
+                                height: nested ? undefined : NumCast(pair.layout._height),
+                                // width: NumCast(pair.layout._width),
+                                // height: NumCast(pair.layout._height),
                             }}  >
                             <DocumentView
                                 Document={pair.layout}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a29f2f662..ae3107b08 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -48,6 +48,7 @@ import { RadialMenu } from './RadialMenu';
 import React = require("react");
 import { ScriptingBox } from "./ScriptingBox";
 import { FormattedTextBox } from "./formattedText/FormattedTextBox";
+import { ColorScheme } from "../../util/SettingsManager";
 const { Howl } = require('howler');
 
 interface Window {
@@ -132,7 +133,7 @@ export interface DocumentViewSharedProps {
 export interface DocumentViewProps extends DocumentViewSharedProps {
     // properties specific to DocumentViews but not to FieldView
     freezeDimensions?: boolean;
-    hideResizeHandles?: boolean; // whether to suppress DocumentDecorations when this document is selected 
+    hideResizeHandles?: boolean; // whether to suppress DocumentDecorations when this document is selected
     hideTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
     hideDecorationTitle?: boolean;  // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings
     treeViewDoc?: Doc;
@@ -420,13 +421,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
     focus = (anchor: Doc, options?: DocFocusOptions) => {
         LightboxView.SetCookie(StrCast(anchor["cookies-set"]));
-        // copying over VIEW fields immediately allows the view type to switch to create the right _componentView
-        Array.from(Object.keys(Doc.GetProto(anchor))).filter(key => key.startsWith(ViewSpecPrefix)).forEach(spec => {
-            this.layoutDoc[spec.replace(ViewSpecPrefix, "")] = ((field) => field instanceof ObjectField ? ObjectField.MakeCopy(field) : field)(anchor[spec]);
-        });
+              // copying over VIEW fields immediately allows the view type to switch to create the right _componentView
+              Array.from(Object.keys(Doc.GetProto(anchor))).filter(key => key.startsWith(ViewSpecPrefix)).forEach(spec => {
+                this.layoutDoc[spec.replace(ViewSpecPrefix, "")] = ((field) => field instanceof ObjectField ? ObjectField.MakeCopy(field) : field)(anchor[spec]);
+            });        
         // after  a timeout, the right _componentView should have been created, so call it to update its view spec values
         setTimeout(() => this._componentView?.setViewSpec?.(anchor, LinkDocPreview.LinkInfo ? true : false));
-        const focusSpeed = this._componentView?.scrollFocus?.(anchor, !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here      
+        const focusSpeed = this._componentView?.scrollFocus?.(anchor, !LinkDocPreview.LinkInfo); // bcz: smooth parameter should really be passed into focus() instead of inferred here
         const endFocus = focusSpeed === undefined ? options?.afterFocus : async (moved: boolean) => options?.afterFocus ? options?.afterFocus(true) : ViewAdjustment.doNothing;
         this.props.focus(options?.docTransform ? anchor : this.rootDoc, {
             ...options, afterFocus: (didFocus: boolean) =>
@@ -764,7 +765,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             !Doc.UserDoc().novice && helpItems.push({ description: "Print DataDoc in Console", event: () => console.log(this.props.Document[DataSym]), icon: "hand-point-right" });
             cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
         }
-
+        
         if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
         cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
         DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
@@ -949,12 +950,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     }
     @computed get renderDoc() {
         TraceMobx();
+        const isButton: boolean = this.props.Document.type === DocumentType.FONTICON;
         if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || this.hidden) return null;
         return this.docContents ??
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 id={this.props.Document[Id]}
                 style={{
-                    background: this.backgroundColor,
+                    background: isButton ? undefined : this.backgroundColor,
                     opacity: this.opacity,
                     color: StrCast(this.layoutDoc.color, "inherit"),
                     fontFamily: StrCast(this.Document._fontFamily, "inherit"),
@@ -970,7 +972,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     }
     render() {
         const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : 0) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString
-        const highlightColor = (CurrentUserUtils.ActiveDashboard?.darkScheme ?
+        const highlightColor = (Doc.UserDoc().colorScheme === ColorScheme.Dark ?
             ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] :
             ["transparent", "#4476F7", "#4476F7", "yellow", "magenta", "cyan", "orange"])[highlightIndex];
         const highlightStyle = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"][highlightIndex];
@@ -982,6 +984,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         const internal = PresBox.EffectsProvider(this.layoutDoc, this.renderDoc) || this.renderDoc;
         const boxShadow = this.props.treeViewDoc ? null : highlighting && this.borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` :
             this.boxShadow || (this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined);
+
+        // Return surrounding highlight 
         return <div className={DocumentView.ROOT_DIV} ref={this._mainCont}
             onContextMenu={this.onContextMenu}
             onKeyDown={this.onKeyDown}
@@ -1142,14 +1146,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         TraceMobx();
         const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
         const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
+        const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
         return (<div className="contentFittingDocumentView">
             {!this.props.Document || !this.props.PanelWidth() ? (null) : (
                 <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
                     style={{
                         position: this.props.Document.isInkMask ? "absolute" : undefined,
-                        transform: `translate(${this.centeringX}px, ${this.centeringY}px)`,
-                        width: xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
-                        height: yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
+                        transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
+                        width: isButton ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
+                        height: isButton ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :
                             `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`),
                     }}>
                     <DocumentViewInternal {...this.props}
diff --git a/src/client/views/nodes/button/FontIconBadge.tsx b/src/client/views/nodes/button/FontIconBadge.tsx
index 3be723052..3e451eea6 100644
--- a/src/client/views/nodes/button/FontIconBadge.tsx
+++ b/src/client/views/nodes/button/FontIconBadge.tsx
@@ -1,11 +1,10 @@
-
-import { AclPrivate, Doc, DocListCast } from '../../../../fields/Doc';
-import { GetEffectiveAcl } from '../../../../fields/util';
+import { observer } from "mobx-react";
+import React from "react";
+import { AclPrivate, Doc, DocListCast } from "../../../../fields/Doc";
+import { GetEffectiveAcl } from "../../../../fields/util";
 import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../../Utils";
-import { DragManager } from '../../../util/DragManager';
-import './FontIconBox.scss';
-import { observer } from 'mobx-react';
-import React from 'react';
+import { DragManager } from "../../../util/DragManager";
+
 interface FontIconBadgeProps {
     collection: Doc | undefined;
 }
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index d4f1b9379..46a499466 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -1,103 +1,205 @@
 @import "../../global/globalCssVariables";
 
-.fontIconBox-label {
-    color: $white;
-    margin-right: 4px;
-    margin-top: 1px;
-    position: relative;
-    text-align: center;
-    font-size: 7px;
-    letter-spacing: normal;
-    background-color: inherit;
-    border-radius: 8px;
-    margin-top: -8px;
-    padding: 0;
-    width: 100%;
-}
+.menuButton {
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    font-size: 80%;
+    border-radius: 7px;
 
-.fontIconBadge-container {
-    position:absolute;
-    z-index: 1000;
-    top: 12px;
+    .menuButton-wrap {
+        grid-column: 1;
+        justify-content: center;
+        align-items: center;
+        text-align: center;
+    }
 
-    .fontIconBadge {
-        position: absolute;
-        top: -10px;
-        right: -10px;
+    .fontIconBox-label {
         color: $white;
-        background: $pink;
-        font-weight: 300;
-        border-radius: 100%;
-        width: 25px;
-        height: 25px;
+        position: relative;
         text-align: center;
-        padding-top: 4px;
-        font-size: 12px;
+        font-size: 7px;
+        letter-spacing: normal;
+        background-color: inherit;
+        margin-top: 5px;
+        border-radius: 8px;
+        padding: 0;
+        width: 100%;
+        font-family: 'ROBOTO';
+        text-transform: uppercase;
+        font-weight: bold;
     }
-}
 
-.menuButton-circle,
-.menuButton-round {
-    border-radius: 100%;
-    background-color: $dark-gray;
-    padding: 0;
-
-    .fontIconBox-label {
-        //margin-left: -10px; // button padding is 10px;
-        bottom: 0;
-        position: absolute;
+    .fontIconBox-icon {
+        width: 80%;
+        height: 80%;
     }
 
-    &:hover {
-        background-color: $light-gray;
+    &.clickBtn {
+        cursor: pointer;
     }
-}
 
-.menuButton-square {
-    padding-top: 3px;
-    padding-bottom: 3px;
-    background-color: $dark-gray;
+    &.tglBtn {
+        cursor: pointer;
+    }
 
-    .fontIconBox-label {
+    &.menuBtn {
+        cursor: pointer;
         border-radius: 0px;
-        margin-top: 0px;
-        border-radius: "inherit";
+        flex-direction: column;
+
+        svg {
+            width: 45% !important;
+            height: 45%;
+        }
     }
-}
 
-.menuButton,
-.menuButton-circle,
-.menuButton-round,
-.menuButton-square {
-    margin-left: -5%;
-    width: 110%;
-    height: 100%;
-    pointer-events: all;
-    touch-action: none;
+    &.colorBtn {
+        color: black;
+        cursor: pointer;
+        flex-direction: row;
+        background: transparent;
 
-    .menuButton-wrap {
-        touch-action: none;
-        border-radius: 8px;
-        width: 100%;
+        .menuButton-dropdownBox {
+            position: absolute;
+            width: 150px;
+            height: 250px;
+            top: 100%;
+            z-index: 21;
+            background-color: #e3e3e3;
+            box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+            border-radius: 3px;
+        }
     }
 
-    .menuButton-icon-square {
-        width: auto;
-        height: 29px;
-        padding: 4px;
+    &.drpdownList {
+        width: 100px;
+        display: grid;
+        grid-auto-columns: 80px 20px;
+        justify-items: flex-start;
+        padding-left: 10px;
+        font-family: 'Roboto';
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        font-size: 13;
+        font-weight: 600;
+        overflow: hidden;
+        cursor: pointer;
+        background: transparent;
+
+        .menuButton-dropdownList {
+            position: absolute;
+            width: 150px;
+            height: fit-content;
+            top: 100%;
+            z-index: 21;
+            background-color: #e3e3e3;
+            box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+            border-radius: 3px;
+
+            .list-item {
+                color: black;
+                width: 100%;
+                height: 25px;
+                display: flex;
+                justify-content: left;
+                align-items: center;
+                padding-left: 5px;
+            }
+
+            .list-item:hover {
+                background-color:lightgrey;
+            }
+        }
     }
 
-    svg {
-        width: 95% !important;
-        height: 95%;
+    &.drpDownBtn {
+        cursor: pointer;
+        background: transparent;
+
+        &.true {
+            background: rgba(0, 0, 0, 0.3);
+        }
+
+        .menuButton-dropdownBox {
+            position: absolute;
+            width: 150px;
+            height: 250px;
+            top: 100%;
+            background-color: #e3e3e3;
+            box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+            border-radius: 3px;
+        }
     }
+
 }
-.menuButton-round {
-    width: 100%;
-    svg {
-        width: 50% !important;
-        height: 50%;
-        position: relative;
-        bottom: 2px;
-    }
-}
\ No newline at end of file
+
+
+// .fontIconBadge-container {
+//     position: absolute;
+//     z-index: 1000;
+//     top: 12px;
+
+//     .fontIconBadge {
+//         position: absolute;
+//         top: -10px;
+//         right: -10px;
+//         color: $white;
+//         background: $pink;
+//         font-weight: 300;
+//         border-radius: 100%;
+//         width: 25px;
+//         height: 25px;
+//         text-align: center;
+//         padding-top: 4px;
+//         font-size: 12px;
+//     }
+// }
+
+// .menuButton-circle,
+// .menuButton-round {
+//     border-radius: 100%;
+//     background-color: $dark-gray;
+//     padding: 0;
+
+//     .fontIconBox-label {
+//         z-index: 100;
+//         min-width: fit-content;
+//         bottom: 0;
+//         left: 0;
+//         width: 100%;
+//         /* justify-self: center; */
+//         border-radius: 0px;
+//         position: absolute;
+//     }
+
+//     .menuButton-dropdown {
+//         display: flex;
+//         justify-content: center;
+//         align-items: center;
+//         font-size: 15px;
+//         /* background-color: #b9b9b9; */
+//         grid-column: 2;
+//         border-radius: 0px 7px 7px 0px;
+//         /* position: absolute; */
+//         width: 13px;
+//         height: 100%;
+//         right: 0;
+//     }
+
+//     &:hover {
+//         background-color: $light-gray;
+//     }
+
+//     .dropbox-background {
+//         width: 100vw;
+//         height: 100vh;
+//         top: 0;
+//         z-index: 20;
+//         left: 0;
+//         background:transparent;
+//         position: fixed;
+//     }
+// }
+
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index f98d01dfc..2c6369e9f 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -2,20 +2,19 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
-import React from 'react';
+import * as React from 'react';
 import { ColorState, SketchPicker } from 'react-color';
 import { Doc, StrListCast } from '../../../../fields/Doc';
 import { createSchema, makeInterface } from '../../../../fields/Schema';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, StrCast, ScriptCast } from '../../../../fields/Types';
 import { SelectionManager } from '../../../util/SelectionManager';
 import { ColorScheme } from '../../../util/SettingsManager';
 import { undoBatch, UndoManager } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
 import { StyleProp } from '../../StyleProvider';
-import { FieldView, FieldViewProps } from '../FieldView';
-import { FontIconBadge } from './FontIconBadge';
+import { FieldView, FieldViewProps } from '.././FieldView';
 import './FontIconBox.scss';
 const FontIconSchema = createSchema({
     icon: "string",
@@ -31,10 +30,14 @@ export enum ButtonType {
     ColorButton = "colorBtn"
 }
 
+export interface ButtonProps extends FieldViewProps {
+    type?: ButtonType;
+}
+
 type FontIconDocument = makeInterface<[typeof FontIconSchema]>;
 const FontIconDocument = makeInterface(FontIconSchema);
 @observer
-export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(FontIconDocument) {
+export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(FontIconDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
     showTemplate = (): void => {
         const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
@@ -56,8 +59,6 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
 
     // Determining UI Specs
     @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
-    @observable private color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-    @observable private backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
     @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
     @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
     @observable private dropdownDirection: string = StrCast(this.rootDoc.dropDownDirection);
@@ -82,16 +83,18 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
      */
     @computed get dropdownButton() {
         const active: string = StrCast(this.rootDoc.dropDownOpen);
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         return (
             <div className={`menuButton ${this.type} ${active}`}
-                style={{ color: "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                 onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}>
-                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} />
-                {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}> {this.label} </div>}
+                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
                 <div
                     className="menuButton-dropdown"
                     style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
-                    <FontAwesomeIcon icon={'caret-down'} color={"black"} size="sm" />
+                    <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
                 </div>
                 {this.rootDoc.dropDownOpen ?
                     <div className="menuButton-dropdownBox"
@@ -121,14 +124,16 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
      * Default
      */
     @computed get defaultButton() {
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const active: string = StrCast(this.rootDoc.dropDownOpen);
         return (
             <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu}
                 style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
                 <div className="menuButton-wrap">
                     <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} />
-                    {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}> {this.label} </div>}
-                    <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} />
+                    {!this.label || !Doc.UserDoc()._showLabel ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
+                    {/* <FontIconBadge collection={Cast(this.rootDoc.watchedDocuments, Doc, null)} /> */}
                 </div>
             </div>
         )
@@ -136,6 +141,8 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
 
 
     render() {
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         // Variables called through eval (from button)
         const canUndo: boolean = UndoManager.CanUndo();
         const canRedo: boolean = UndoManager.CanRedo();
@@ -144,7 +151,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
         const userDoc = Doc.UserDoc();
 
         // Toggle and canClick properties as determined from the variable passed into the button doc
-        // const toggle = this.rootDoc.toggle ? ScriptCast(this.rootDoc.toggle) : undefined;
+        const toggle = this.rootDoc.toggle ? ScriptCast(this.rootDoc.toggle) : undefined;
         const canClick: boolean = this.rootDoc.canClick ? eval(StrCast(this.rootDoc.canClick)) : false;
         // if (toggle) {
         //     console.log(StrCast(this.rootDoc.title), toggle);
@@ -154,11 +161,11 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
 
         const active: string = StrCast(this.rootDoc.dropDownOpen);
         const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}>
+            <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
                 {this.label}
             </div>;
         const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color: this.color, backgroundColor: this.backgroundColor }}>
+            <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
                 {this.label}
             </div>;
         const dropdownCaret = <div
@@ -166,7 +173,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
             style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
             <FontAwesomeIcon icon={'caret-down'} color={"black"} size="sm" />
         </div>;
-        const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(this.backgroundColor)}
+        const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(backgroundColor)}
             presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
                 '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
                 '#FFFFFF', '#f1efeb', 'transparent']} />;
@@ -207,9 +214,9 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
             case ButtonType.DropdownList:
                 button = (
                     <div className={`menuButton ${this.type} ${active}`}
-                        style={{ backgroundColor: this.rootDoc.dropDownOpen ? "#aeddf880" : undefined, color: this.rootDoc.dropDownOpen ? "#1c5c96" : "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                        style={{ backgroundColor: this.rootDoc.dropDownOpen ? "#aeddf880" : backgroundColor, color: this.rootDoc.dropDownOpen ? "#1c5c96" : color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                         onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}>
-                        {/* {toggle} */}
+                        {toggle}
                         {label}
                         {dropdownCaret}
                         {this.rootDoc.dropDownOpen ?
@@ -227,10 +234,10 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
             case ButtonType.ColorButton:
                 button = (
                     <div className={`menuButton ${this.type} ${active}`}
-                        style={{ opacity: selectedDoc ? 1 : 0.5, color: dark ? "white" : "black", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                        style={{ opacity: selectedDoc ? 1 : 0.5, color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                         onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}
                         onPointerDown={e => e.stopPropagation()}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={dark ? "white" : "black"} />
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {label}
                         {dropdownCaret}
                         {this.rootDoc.dropDownOpen ?
@@ -247,40 +254,36 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
                     </div>
                 );
                 break;
-            // case ButtonType.ToggleButton:
-            //     button = (
-            //         <div className={`menuButton ${this.type}`} style={{ opacity: canClick ? 1 : 0.4, backgroundColor: toggle ? this.backgroundColor : undefined }}>
-            //             <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={toggle ? this.color : this.backgroundColor} />
-            //             {label}
-            //         </div>
-            //     );
-            //     break;
+            case ButtonType.ToggleButton:
+                button = (
+                    <div className={`menuButton ${this.type}`} style={{ opacity: canClick ? 1 : 0.4, backgroundColor: toggle ? backgroundColor : undefined }}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={toggle ? color : backgroundColor} />
+                        {label}
+                    </div>
+                );
+                break;
             case ButtonType.ClickButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ color: this.color, backgroundColor: this.backgroundColor, opacity: canClick ? 1 : 0.4 }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} />
+                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: canClick ? 1 : 0.4 }}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {label}
                     </div>
                 );
                 break;
             case ButtonType.DoubleButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ color: this.color, backgroundColor: this.backgroundColor }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={this.color} />
+                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor }}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {label}
                     </div>
                 );
                 break;
             case ButtonType.MenuButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ color: dark ? "white" : "black", backgroundColor: dark ? "black" : "lightgrey" }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={dark ? "white" : "black"} />
+                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor }}>
+                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {menuLabel}
                     </div >
-                    // <div className={`menuButton ${type}`} style={{ color, backgroundColor }}>
-                    //     <FontAwesomeIcon className={`fontIconBox-icon-${type}`} icon={icon} color={color} />
-                    //     {label}
-                    // </div>
                 );
                 break;
             default:
-- 
cgit v1.2.3-70-g09d2


From d5841cda5aa838cf02b26a7ffbcc2b1713a66f36 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 19 Aug 2021 17:43:33 -0400
Subject: menu nearing final updates

---
 src/client/documents/Documents.ts                  |    2 +
 src/client/util/CurrentUserUtils.ts                |  115 +-
 src/client/util/tempCurrentUserUtils.ts            | 1389 --------------------
 src/client/views/DocumentButtonBar.tsx             |    5 +-
 src/client/views/collections/CollectionMenu.tsx    |    1 +
 .../collectionLinearView/CollectionLinearView.scss |   11 +-
 .../collectionLinearView/CollectionLinearView.tsx  |    2 +-
 src/client/views/nodes/button/ButtonScripts.ts     |   14 +
 src/client/views/nodes/button/FontIconBox.scss     |   64 +-
 src/client/views/nodes/button/FontIconBox.tsx      |  375 ++++--
 10 files changed, 414 insertions(+), 1564 deletions(-)
 delete mode 100644 src/client/util/tempCurrentUserUtils.ts
 create mode 100644 src/client/views/nodes/button/ButtonScripts.ts

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 817fbb9d6..f6b2e0736 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -223,11 +223,13 @@ export class DocumentOptions {
     docColorBtn?: string;
     userColorBtn?: string;
     canClick?: string;
+    script?: string;
 
     //LINEAR VIEW
     linearViewIsExpanded?: boolean; // is linear view expanded
     linearViewExpandable?: boolean; // can linear view be expanded
     linearViewToggleButton?: string; // button to open close linear view group
+    linearViewSubMenu?: boolean;
 
     layout_linkView?: Doc; // view template for a link document
     layout_keyValue?: string; // view tempalte for key value docs
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index d03ef4aca..4ff0446ad 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -923,44 +923,58 @@ export class CurrentUserUtils {
                 title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
                 list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
                     "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
-                scriptDoc: Doc.UserDoc(), toggle: 'userDoc._fontFamily'
+                script: 'changeFont'
             },
+            { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", click: 'toggleBold()', script: 'toggleBold' },
+            { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", click: 'toggleItalic()', script: 'toggleItalic' },
+            { title: "Underline", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", click: 'toggleUnderline()', script: 'toggleUnderline' },
+            // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()'},
+            // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()'},
+            // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()'},
+            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._highlightColor' },
+            { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "fill-drip", ignoreClick: true, scriptDoc: Doc.UserDoc(), script:'console.log("test")', userColorBtn: 'userDoc._textColor' },
+        ];
+    }
+
+    static inkTools(doc: Doc) {
+        return [
+            { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'togglePen()', script: 'togglePen' },
+            { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", click: 'toggleHighlighter()', script: 'toggleHighlighter' },
+            { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle", click: 'toggleCircle()', script: 'toggleCircle' },
+            { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square", click: 'toggleSquare()', script: 'toggleSquare' },
+            { title: "Line", toolTip: "Line (Ctrl+Shift+L)", btnType: ButtonType.ToggleButton, icon: "fill-drip", click: 'toggleLine()', script: 'toggleLine' },
+        ];
+    }
+
+    static webTools(doc: Doc) {
+        return [
             {
-                title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", click: 'toggleBold()',
-                scriptDoc: Doc.UserDoc(),
-                toggle: 'userDoc._boldActive'
+                title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
+                list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
+                    "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
+                script: 'changeFont'
             },
-            { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", click: 'toggleItalic()', scriptDoc: Doc.UserDoc(), toggle: 'userDoc._italicsActive' },
-            { title: "Underline", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", click: 'toggleUnderline()', scriptDoc: Doc.UserDoc(), toggle: 'userDoc._underlineActive' },
-            // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()', toggle: 'userDoc._underlineActive' },
-            // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()', toggle: 'userDoc._underlineActive' },
-            // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()', toggle: 'userDoc._underlineActive' },
-            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._highlightColor' },
-            { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "fill-drip", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._textColor' },
-            // { title: "Link", tooltip: "Link", btnType: ButtonType.DropdownButton, icon: "link", click: '', ignoreClick: true },
         ];
     }
 
     static async contextMenuBtnDescriptions(doc: Doc) {
         return [
-            // { title: "Perspective", tooltip: "Change document's perspective", type: "btn", btnType: ButtonType.DropdownButton, ignoreClick: true, icon: "desktop", click: '' },
             {
-                title: "Perspective", toolTip: "Perspective", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
+                title: "Perspective", toolTip: "View", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
                 list: [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Tree,
-                CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn,
-                CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel,
-                CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
-                CollectionViewType.Grid],
-                scriptDoc: 'selectedDoc',
-                toggle: 'selectedDoc._viewType'
+                    CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn,
+                    CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel,
+                    CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
+                    CollectionViewType.Grid],
+                script: 'changeView',
             },
             {
-                title: "Background", toolTip: "Background", btnType: ButtonType.ColorButton, scriptDoc: 'selectedDoc',
-                docColorBtn: 'selectedDoc.backgroundColor', width: 60, ignoreClick: true, icon: "fill-drip",
-                canClick: 'numSelected > 0'
+                title: "Background", toolTip: "Background", btnType: ButtonType.ColorButton, width: 60, ignoreClick: true, icon: "fill-drip",
+                script: "changeBackgroundColor"
             },
-            { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()', toggle: 'selectedDoc.z', canClick: 'numSelected > 0' },
-            { title: "Text Tools", type: "TextMenu", icon: "font" },
+            { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()' },
+            { title: "Text", type: "TextMenu" },
+            { title: "Ink & GFX", type: "InkMenu" },
             // { title: "Ink Tools", type: "LinearMenu", icon: "pen-nib" },
             // { title: "GFX Tools", type: "LinearMenu", icon: "shapes" },
             // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy" },
@@ -971,21 +985,44 @@ export class CurrentUserUtils {
     static async setupContextMenuButtons(doc: Doc) {
         const docList: Doc[] = [];
 
-        const contextMenuBtns = (await CurrentUserUtils.contextMenuBtnDescriptions(doc)).map(({ title, width, toolTip, ignoreClick, icon, type, btnType, click, toggle, scriptDoc, canClick, docColorBtn }) => {
+        const contextMenuBtns = (await CurrentUserUtils.contextMenuBtnDescriptions(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, type, btnType, click, script }) => {
             const textDocList: Doc[] = [];
             if (type === "TextMenu") {
-                const textBtns = (CurrentUserUtils.textTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, btnType, click, toggle, scriptDoc, userColorBtn }) => {
+                const textBtns = (CurrentUserUtils.textTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, btnType, click, script, userColorBtn }) => {
                     textDocList.push(Docs.Create.FontIconDocument({
-                        _nativeWidth: width ? width : 25,
-                        _nativeHeight: 25,
-                        _width: width ? width : 25,
-                        _height: 25,
+                        _nativeWidth: width ? width : 30,
+                        _nativeHeight: 30,
+                        _width: width ? width : 30,
+                        _height: 30,
                         icon,
                         toolTip,
                         userColorBtn,
-
-                        // testToggle: toggle ? ScriptField.MakeScript(toggle, { this: scriptDoc, scriptContext: "any" }) : undefined,
-                        // toggle: toggle,
+                        script,
+                        btnType: btnType,
+                        btnList: new List<string>(list),
+                        ignoreClick: ignoreClick,
+                        _stayInCollection: true,
+                        _hideContextMenu: true,
+                        system: true,
+                        dontUndo: true,
+                        title,
+                        backgroundColor: "black",
+                        _dropAction: "alias",
+                        _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
+                        onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
+                    }));
+                });
+                docList.push(CurrentUserUtils.blist({ linearViewSubMenu: true, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
+            } else if (type === "InkMenu") {
+                const inkBtns = (CurrentUserUtils.inkTools(doc)).map(({ title, toolTip, icon, btnType, click }) => {
+                    textDocList.push(Docs.Create.FontIconDocument({
+                        _nativeWidth: width ? width : 30,
+                        _nativeHeight: 30,
+                        _width: width ? width : 30,
+                        _height: 30,
+                        icon,
+                        toolTip,
+                        script,
                         btnType: btnType,
                         btnList: new List<string>(list),
                         ignoreClick: ignoreClick,
@@ -997,10 +1034,10 @@ export class CurrentUserUtils {
                         backgroundColor: "black",
                         _dropAction: "alias",
                         _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
-                        onClick: click ? ScriptField.MakeScript(click, { scriptContext: "any" }) : undefined
+                        onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
                     }));
                 });
-                docList.push(CurrentUserUtils.blist({ ignoreClick: true, linearViewExpandable: true, icon:"Text", _height: 30, backgroundColor: "transparent" }, textDocList));
+                docList.push(CurrentUserUtils.blist({ linearViewSubMenu: true, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
             } else {
                 docList.push(Docs.Create.FontIconDocument({
                     _nativeWidth: width ? width : 30,
@@ -1011,9 +1048,9 @@ export class CurrentUserUtils {
                     toolTip,
                     // testToggle: toggle ? ScriptField.MakeScript(toggle, { scriptContext: "any" }) : undefined,
                     // toggle: toggle,
-                    docColorBtn,
-                    canClick: canClick,
+                    script,
                     btnType: btnType,
+                    btnList: new List<string>(list),
                     ignoreClick: ignoreClick,
                     _stayInCollection: true,
                     _hideContextMenu: true,
@@ -1093,7 +1130,7 @@ export class CurrentUserUtils {
         }
         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 });
+            const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", type: ButtonType.ToolButton, icon: "upload", 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" }));
         }
     }
diff --git a/src/client/util/tempCurrentUserUtils.ts b/src/client/util/tempCurrentUserUtils.ts
deleted file mode 100644
index 3fba672e6..000000000
--- a/src/client/util/tempCurrentUserUtils.ts
+++ /dev/null
@@ -1,1389 +0,0 @@
-import { computed, observable, reaction, action } from "mobx";
-import * as rp from 'request-promise';
-import { DataSym, Doc, DocListCast, DocListCastAsync, AclReadonly } from "../../fields/Doc";
-import { Id } from "../../fields/FieldSymbols";
-import { List } from "../../fields/List";
-import { PrefetchProxy } from "../../fields/Proxy";
-import { RichTextField } from "../../fields/RichTextField";
-import { listSpec } from "../../fields/Schema";
-import { SchemaHeaderField } from "../../fields/SchemaHeaderField";
-import { ComputedField, ScriptField } from "../../fields/ScriptField";
-import { BoolCast, Cast, NumCast, PromiseValue, StrCast, DateCast } from "../../fields/Types";
-import { nullAudio } from "../../fields/URLField";
-import { SharingPermissions } from "../../fields/util";
-import { Utils } from "../../Utils";
-import { DocServer } from "../DocServer";
-import { Docs, DocumentOptions, DocUtils } from "../documents/Documents";
-import { DocumentType } from "../documents/DocumentTypes";
-import { Networking } from "../Network";
-import { CollectionDockingView } from "../views/collections/collectionDocking/CollectionDockingView";
-import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView";
-import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
-import { MainView } from "../views/MainView";
-import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
-import { LabelBox } from "../views/nodes/LabelBox";
-import { OverlayView } from "../views/OverlayView";
-import { DocumentManager } from "./DocumentManager";
-import { DragManager } from "./DragManager";
-import { makeTemplate } from "./DropConverter";
-import { HistoryUtil } from "./History";
-import { LinkManager } from "./LinkManager";
-import { Scripting } from "./Scripting";
-import { SearchUtil } from "./SearchUtil";
-import { SelectionManager } from "./SelectionManager";
-import { SnappingManager } from "./SnappingManager";
-import { InkTool } from "../../fields/InkField";
-import { ButtonType } from "../views/nodes/FontIconBox";
-
-
-export let resolvedPorts: { server: number, socket: number };
-const headerViewVersion = "0.1";
-export class CurrentUserUtils {
-    private static curr_id: string;
-    //TODO tfs: these should be temporary...
-    private static mainDocId: string | undefined;
-
-    public static get id() { return this.curr_id; }
-    public static get MainDocId() { return this.mainDocId; }
-    public static set MainDocId(id: string | undefined) { this.mainDocId = id; }
-    @computed public static get UserDocument() { return Doc.UserDoc(); }
-
-    @observable public static GuestTarget: Doc | undefined;
-    @observable public static GuestDashboard: Doc | undefined;
-    @observable public static GuestMobile: Doc | undefined;
-    @observable public static propertiesWidth: number = 0;
-
-    // sets up the default User Templates - slideView,  headerView
-    static setupUserTemplateButtons(doc: Doc) {
-        // Prototype for mobile button (not sure if 'Advanced Item Prototypes' is ideal location)
-        if (doc["template-mobile-button"] === undefined) {
-            const queryTemplate = this.mobileButton({
-                title: "NEW MOBILE BUTTON",
-                onClick: undefined,
-            },
-                [this.ficon({
-                    ignoreClick: true,
-                    icon: "mobile",
-                    btnType: ButtonType.ClickButton,
-                    backgroundColor: "transparent"
-                }),
-                this.mobileTextContainer({},
-                    [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]);
-            doc["template-mobile-button"] = CurrentUserUtils.ficon({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button",
-                btnType: ButtonType.ClickButton,
-                icon: "mobile"
-            });
-        }
-
-        if (doc["template-button-slides"] === undefined) {
-            const slideTemplate = Docs.Create.MultirowDocument(
-                [
-                    Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }),
-                    Docs.Create.TextDocument("", { title: "text", _height: 100, system: true })
-                ],
-                { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
-            );
-            slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
-            doc["template-button-slides"] = CurrentUserUtils.ficon({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide",
-                icon: "address-card",
-                btnType: ButtonType.ClickButton
-            });
-        }
-
-        if (doc["template-button-link"] === undefined) {  // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to.
-            const linkTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _autoHeight: true, system: true }, "header")); // text needs to be a space to allow templateText to be created
-            linkTemplate.system = true;
-            Doc.GetProto(linkTemplate).layout =
-                "<div>" +
-                "    <FormattedTextBox {...props} dontSelectOnLoad={'true'} height='{this._headerHeight||75}px' ignoreAutoHeight={'true'} background='{this._headerColor||`lightGray`}' fieldKey={'header'}/>" +
-                "    <FormattedTextBox {...props} position='absolute' top='{(this._headerHeight||75)*scale}px' height='calc({100/scale}% - {this._headerHeight||75}px)' fieldKey={'text'}/>" +
-                "</div>";
-            (linkTemplate.proto as Doc).isTemplateDoc = makeTemplate(linkTemplate.proto as Doc, true, "linkView");
-
-            const rtf2 = {
-                doc: {
-                    type: "doc", content: [
-                        {
-                            type: "paragraph",
-                            content: [{
-                                type: "dashField",
-                                attrs: {
-                                    fieldKey: "src",
-                                    hideKey: false
-                                }
-                            }]
-                        },
-                        { type: "paragraph" },
-                        {
-                            type: "paragraph",
-                            content: [{
-                                type: "dashField",
-                                attrs: {
-                                    fieldKey: "dst",
-                                    hideKey: false
-                                }
-                            }]
-                        }]
-                },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
-            };
-            linkTemplate.header = new RichTextField(JSON.stringify(rtf2), "");
-
-            doc["template-button-link"] = CurrentUserUtils.ficon({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view",
-                btnType: ButtonType.ClickButton,
-                icon: "window-maximize", system: true
-            });
-        }
-
-        if (doc["template-button-switch"] === undefined) {
-            const { FreeformDocument, MulticolumnDocument, TextDocument } = Docs.Create;
-
-            const yes = FreeformDocument([], { title: "yes", _height: 35, _width: 50, _dimUnit: DimUnit.Pixel, _dimMagnitude: 40, system: true });
-            const name = TextDocument("name", { title: "name", _height: 35, _width: 70, _dimMagnitude: 1, system: true });
-            const no = FreeformDocument([], { title: "no", _height: 100, _width: 100, system: true });
-            const labelTemplate = {
-                doc: {
-                    type: "doc", content: [{
-                        type: "paragraph",
-                        content: [{ type: "dashField", attrs: { fieldKey: "PARAMS", hideKey: true } }]
-                    }]
-                },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
-            };
-            Doc.GetProto(name).text = new RichTextField(JSON.stringify(labelTemplate), "PARAMS");
-            Doc.GetProto(yes).backgroundColor = ComputedField.MakeFunction("self[this.PARAMS] ? 'green':'red'");
-            // Doc.GetProto(no).backgroundColor = ComputedField.MakeFunction("!self[this.PARAMS] ? 'red':'white'");
-            // Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = true");
-            Doc.GetProto(yes).onClick = ScriptField.MakeScript("self[this.PARAMS] = !self[this.PARAMS]");
-            // Doc.GetProto(no).onClick = ScriptField.MakeScript("self[this.PARAMS] = false");
-            const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, system: true });
-            box.isTemplateDoc = makeTemplate(box, true, "switch");
-
-            doc["template-button-switch"] = CurrentUserUtils.ficon({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch",
-                btnType: ButtonType.ClickButton,
-                icon: "toggle-on", system: true
-            });
-        }
-
-        if (doc["template-button-detail"] === undefined) {
-            const { TextDocument, MasonryDocument, CarouselDocument } = Docs.Create;
-
-            const openInTarget = ScriptField.MakeScript("openOnRight(self.doubleClickView)");
-            const carousel = CarouselDocument([], {
-                title: "data", _height: 350, _itemIndex: 0, "_carousel-caption-xMargin": 10, "_carousel-caption-yMargin": 10,
-                onChildDoubleClick: openInTarget, backgroundColor: "#9b9b9b3F", system: true
-            });
-
-            const details = TextDocument("", { title: "details", _height: 200, _autoHeight: true, system: true });
-            const short = TextDocument("", { title: "shortDescription", treeViewOpen: true, treeViewExpandedView: "layout", _height: 75, _autoHeight: true, system: true });
-            const long = TextDocument("", { title: "longDescription", treeViewOpen: false, treeViewExpandedView: "layout", _height: 150, _autoHeight: true, system: true });
-
-            const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
-            const detailedTemplate = {
-                doc: {
-                    type: "doc", content: buxtonFieldKeys.map(fieldKey => ({
-                        type: "paragraph",
-                        content: [{ type: "dashField", attrs: { fieldKey } }]
-                    }))
-                },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
-            };
-            details.text = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
-
-            const shared = { _autoHeight: true, _xMargin: 0 };
-            const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: "12px" };
-            const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTitle: true, _pivotField: "title", system: true };
-
-            const descriptionWrapper = MasonryDocument([details, short, long], { ...shared, ...descriptionWrapperOpts });
-            descriptionWrapper._columnHeaders = new List<SchemaHeaderField>([
-                new SchemaHeaderField("[A Short Description]", "dimGray", undefined, undefined, undefined, false),
-                new SchemaHeaderField("[Long Description]", "dimGray", undefined, undefined, undefined, true),
-                new SchemaHeaderField("[Details]", "dimGray", undefined, undefined, undefined, true),
-            ]);
-            const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts, _chromeHidden: true, system: true });
-            detailView.isTemplateDoc = makeTemplate(detailView);
-
-            details.title = "Details";
-            short.title = "A Short Description";
-            long.title = "Long Description";
-
-            doc["template-button-detail"] = CurrentUserUtils.ficon({
-                onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
-                dragFactory: new PrefetchProxy(detailView) as any as Doc, title: "detailView",
-                btnType: ButtonType.ClickButton,
-                icon: "window-maximize", system: true
-            });
-        }
-
-        const requiredTypes = [
-            doc["template-button-slides"] as Doc,
-            doc["template-mobile-button"] as Doc,
-            doc["template-button-detail"] as Doc,
-            doc["template-button-link"] as Doc,
-            //doc["template-button-switch"] as Doc]
-        ];
-        if (doc["template-buttons"] === undefined) {
-            doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
-                title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
-                hidden: ComputedField.MakeFunction("IsNoviceMode()") as any,
-                _stayInCollection: true, _hideContextMenu: true,
-                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
-                dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
-            }));
-        } else {
-            const curButnTypes = Cast(doc["template-buttons"], Doc, null);
-            DocListCastAsync(curButnTypes.data).then(async curBtns => {
-                curBtns && await Promise.all(curBtns);
-                requiredTypes.map(btype => Doc.AddDocToList(curButnTypes, "data", btype));
-            });
-        }
-        return doc["template-buttons"] as Doc;
-    }
-
-    // setup the different note type skins
-    static setupNoteTemplates(doc: Doc) {
-        if (doc["template-note-Note"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", { title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Note");
-            doc["template-note-Note"] = new PrefetchProxy(noteView);
-        }
-        if (doc["template-note-Idea"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor: "pink", system: true });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea");
-            doc["template-note-Idea"] = new PrefetchProxy(noteView);
-        }
-        if (doc["template-note-Topic"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", { title: "text", backgroundColor: "lightblue", system: true });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic");
-            doc["template-note-Topic"] = new PrefetchProxy(noteView);
-        }
-        if (doc["template-note-Todo"] === undefined) {
-            const noteView = Docs.Create.TextDocument("", {
-                title: "text", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption",
-                layout: FormattedTextBox.LayoutString("Todo"), caption: RichTextField.DashField("taskStatus"), system: true
-            });
-            noteView.isTemplateDoc = makeTemplate(noteView, true, "Todo");
-            doc["template-note-Todo"] = new PrefetchProxy(noteView);
-        }
-        const taskStatusValues = [
-            { title: "todo", _backgroundColor: "blue", color: "white", system: true },
-            { title: "in progress", _backgroundColor: "yellow", color: "black", system: true },
-            { title: "completed", _backgroundColor: "green", color: "white", system: true }
-        ];
-        if (doc.fieldTypes === undefined) {
-            doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations", system: true });
-            DocUtils.addFieldEnumerations(Doc.GetProto(doc["template-note-Todo"] as any as Doc), "taskStatus", taskStatusValues);
-        }
-
-        if (doc["template-notes"] === undefined) {
-            doc["template-notes"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-note-Note"] as any as Doc, doc["template-note-Idea"] as any as Doc, doc["template-note-Topic"] as any as Doc], // doc["template-note-Todo"] as any as Doc],
-                { title: "Note Layouts", _height: 75, system: true }));
-        } else {
-            const curNoteTypes = Cast(doc["template-notes"], Doc, null);
-            const requiredTypes = [doc["template-note-Note"] as any as Doc, doc["template-note-Idea"] as any as Doc, doc["template-note-Topic"] as any as Doc];//, doc["template-note-Todo"] as any as Doc];
-            DocListCastAsync(curNoteTypes.data).then(async curNotes => {
-                curNotes && await Promise.all(curNotes);
-                requiredTypes.map(ntype => Doc.AddDocToList(curNoteTypes, "data", ntype));
-            });
-        }
-
-        return doc["template-notes"] as Doc;
-    }
-
-    // creates Note templates, and initial "user" templates
-    static setupDocTemplates(doc: Doc) {
-        const noteTemplates = CurrentUserUtils.setupNoteTemplates(doc);
-        const userTemplateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
-        const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc);
-        if (doc.templateDocs === undefined) {
-            doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], {
-                title: "template layouts", _xPadding: 0, system: true,
-                dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
-            }));
-        }
-    }
-
-    // setup templates for different document types when they are iconified from Document Decorations
-    static setupDefaultIconTemplates(doc: Doc) {
-        if (doc["template-icon-view"] === undefined) {
-            const iconView = Docs.Create.LabelDocument({
-                title: "icon", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimGray",
-                _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
-            });
-            //  Docs.Create.TextDocument("", {
-            //     title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
-            // });
-            // Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
-            iconView.isTemplateDoc = makeTemplate(iconView);
-            doc["template-icon-view"] = new PrefetchProxy(iconView);
-        }
-        if (doc["template-icon-view-rtf"] === undefined) {
-            const iconRtfView = Docs.Create.LabelDocument({
-                title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
-                _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
-            });
-            iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF);
-            doc["template-icon-view-rtf"] = new PrefetchProxy(iconRtfView);
-        }
-        if (doc["template-icon-view-button"] === undefined) {
-            const iconBtnView = Docs.Create.FontIconDocument({
-                title: "icon_" + DocumentType.BUTTON, _nativeHeight: 30, _nativeWidth: 30,
-                _width: 30, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
-            });
-            iconBtnView.isTemplateDoc = makeTemplate(iconBtnView, true, "icon_" + DocumentType.BUTTON);
-            doc["template-icon-view-button"] = new PrefetchProxy(iconBtnView);
-        }
-        if (doc["template-icon-view-img"] === undefined) {
-            const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", {
-                title: "data", _width: 50, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
-            });
-            iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
-            doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
-        }
-        if (doc["template-icon-view-col"] === undefined) {
-            const iconColView = Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true });
-            iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
-            doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
-        }
-        if (doc["template-icons"] === undefined) {
-            doc["template-icons"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
-            doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-pdf"] as Doc], { title: "icon templates", _height: 75, system: true }));
-        } else {
-            const templateIconsDoc = Cast(doc["template-icons"], Doc, null);
-            const requiredTypes = [doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
-            doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc];
-            DocListCastAsync(templateIconsDoc.data).then(async curIcons => {
-                curIcons && await Promise.all(curIcons);
-                requiredTypes.map(ntype => Doc.AddDocToList(templateIconsDoc, "data", ntype));
-            });
-        }
-        return doc["template-icons"] as Doc;
-    }
-
-    static creatorBtnDescriptors(doc: Doc): {
-        title: string, toolTip: string, icon: string, drag?: string, ignoreClick?: boolean,
-        click?: string, backgroundColor?: string, dragFactory?: Doc, noviceMode?: boolean, clickFactory?: Doc
-    }[] {
-        if (doc.emptyPresentation === undefined) {
-            doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
-                { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyPresentation as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyCollection === undefined) {
-            doc.emptyCollection = Docs.Create.FreeformDocument([],
-                { _nativeWidth: undefined, _nativeHeight: undefined, _fitWidth: true, _width: 150, _height: 100, title: "freeform", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyCollection as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyPane === undefined) {
-            doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _width: 500, _height: 800, title: "Untitled Tab", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptySlide === undefined) {
-            const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text');
-            FormattedTextBox.SelectOnLoad = textDoc[Id];
-            doc.emptySlide = textDoc;
-        }
-        if ((doc.emptyHeader as Doc)?.version !== headerViewVersion) {
-            const json = {
-                doc: {
-                    type: "doc",
-                    content: [
-                        {
-                            type: "paragraph", attrs: {}, content: [{
-                                type: "dashField",
-                                attrs: { fieldKey: "author", docid: "", hideKey: false },
-                                marks: [{ type: "strong" }]
-                            }, {
-                                type: "dashField",
-                                attrs: { fieldKey: "creationDate", docid: "", hideKey: false },
-                                marks: [{ type: "strong" }]
-                            }]
-                        }]
-                },
-                selection: { type: "text", anchor: 1, head: 1 },
-                storedMarks: []
-            };
-            const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), {
-                title: "text", version: headerViewVersion, target: doc, _height: 70, _headerPointerEvents: "all",
-                _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, system: true, _fitWidth: true,
-                cloneFieldFilter: new List<string>(["system"])
-            }, "header");
-            const headerBtnHgt = 10;
-            headerTemplate[DataSym].layout =
-                "<HTMLdiv transformOrigin='top left' width='{100/scale}%' height='{100/scale}%' transform='scale({scale})'>" +
-                `    <FormattedTextBox {...props} dontScale='true' fieldKey={'text'}  height='calc(100% - ${headerBtnHgt}px - {this._headerHeight}px)'/>` +
-                "    <FormattedTextBox {...props} dontScale='true' fieldKey={'header'}  dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize}px' height='{(this._headerHeight||1)}px' background='{this._headerColor ||this.target.mySharedDocs.userColor||`lightGray`}' />" +
-                `    <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(1,this._height-30),this._headerHeight===1?50:1)) && (this._autoHeightMargins=this._headerHeight+${headerBtnHgt})’}  >Metadata</HTMLdiv>` +
-                "</HTMLdiv>";
-
-            // "<div style={'height:100%'}>" +
-            // "    <FormattedTextBox {...props} fieldKey={'header'} dontSelectOnLoad={'true'} ignoreAutoHeight={'true'} pointerEvents='{this._headerPointerEvents||`none`}' fontSize='{this._headerFontSize}px' height='{this._headerHeight}px' background='{this._headerColor||this.target.mySharedDocs.userColor}' />" +
-            // "    <FormattedTextBox {...props} fieldKey={'text'} position='absolute' top='{(this._headerHeight)*scale}px' height='calc({100/scale}% - {this._headerHeight}px)'/>" +
-            // "</div>";
-            (headerTemplate.proto as Doc).isTemplateDoc = makeTemplate(headerTemplate.proto as Doc, true, "headerView");
-            doc.emptyHeader = headerTemplate;
-            ((doc.emptyHeader as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyComparison === undefined) {
-            doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true, cloneFieldFilter: new List<string>(["system"]) });
-        }
-        if (doc.emptyScript === undefined) {
-            doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyScript as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyScreenshot === undefined) {
-            doc.emptyScreenshot = Docs.Create.ScreenshotDocument("empty screenshot", { _fitWidth: true, _width: 400, _height: 200, system: true, cloneFieldFilter: new List<string>(["system"]) });
-        }
-        if (doc.emptyWall === undefined) {
-            doc.emptyWall = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            (doc.emptyWall as Doc).videoWall = true;
-        }
-        if (doc.emptyAudio === undefined) {
-            doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyAudio as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyNote === undefined) {
-            doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", _autoHeight: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyNote as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyImage === undefined) {
-            doc.emptyImage = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth: 250, title: "an image of a cat", system: true });
-        }
-        if (doc.emptyButton === undefined) {
-            doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button", system: true, cloneFieldFilter: new List<string>(["system"]) });
-            ((doc.emptyButton as Doc).proto as Doc)["dragFactory-count"] = 0;
-        }
-        if (doc.emptyWebpage === undefined) {
-            doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, isTemplateDoc: true, _height: 512, _width: 400, useCors: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
-        }
-        if (doc.activeMobileMenu === undefined) {
-            this.setupActiveMobileMenu(doc);
-        }
-        return [
-            { toolTip: "Tap to create a note in a new pane, drag for a note", title: "Note", icon: "sticky-note", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyNote as Doc, noviceMode: true, clickFactory: doc.emptyNote as Doc, },
-            { toolTip: "Tap to create a collection in a new pane, drag for a collection", title: "Col", icon: "folder", click: 'openOnRight(copyDragFactory(this.clickFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyCollection as Doc, noviceMode: true, clickFactory: doc.emptyPane as Doc, },
-            { toolTip: "Tap to create a webpage in a new pane, drag for a webpage", title: "Web", icon: "globe-asia", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWebpage as Doc, noviceMode: true },
-            { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc, noviceMode: true },
-            { toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc },
-            { toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
-            { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true },
-            { 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 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 },
-            { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' },
-        ];
-
-    }
-
-    // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools
-    static async setupCreatorButtons(doc: Doc) {
-        let alreadyCreatedButtons: string[] = [];
-        const dragCreatorSet = await Cast(doc.myItemCreators, Doc, null);
-        if (dragCreatorSet) {
-            const dragCreators = await Cast(dragCreatorSet.data, listSpec(Doc));
-            if (dragCreators) {
-                const dragDocs = await Promise.all(dragCreators);
-                alreadyCreatedButtons = dragDocs.map(d => StrCast(d.title));
-            }
-        }
-        const buttons = CurrentUserUtils.creatorBtnDescriptors(doc).filter(d => !alreadyCreatedButtons?.includes(d.title));
-        const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, backgroundColor, dragFactory, noviceMode, clickFactory }) => Docs.Create.FontIconDocument({
-            _nativeWidth: 50, _nativeHeight: 50, _width: 30, _height: 25,
-            icon,
-            title,
-            toolTip,
-            btnType: ButtonType.ClickButton,
-            ignoreClick,
-            _dropAction: "alias",
-            onDragStart: drag ? ScriptField.MakeFunction(drag) : undefined,
-            onClick: click ? ScriptField.MakeScript(click) : undefined,
-            backgroundColor,
-            _hideContextMenu: true,
-            _removeDropProperties: new List<string>(["_stayInCollection"]),
-            _stayInCollection: true,
-            dragFactory,
-            clickFactory,
-            hidden: !noviceMode ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined,
-            system: true,
-        }));
-
-        if (dragCreatorSet === undefined) {
-            doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
-                title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true,
-                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
-                dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
-            }));
-        } else {
-            creatorBtns.forEach(nb => Doc.AddDocToList(doc.myItemCreators as Doc, "data", nb));
-        }
-        return doc.myItemCreators as Doc;
-    }
-
-    static async menuBtnDescriptions(doc: Doc) {
-        return [
-            { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
-            { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' },
-            { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
-            { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
-            { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
-            { 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: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
-        ];
-    }
-
-    static setupSearchPanel(doc: Doc) {
-        if (doc.mySearchPanelDoc === undefined) {
-            doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({
-                _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true,
-                childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true
-            })) as any as Doc;
-        }
-    }
-    static async setupMenuPanel(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
-        if (doc.menuStack === undefined) {
-            await this.setupSharingSidebar(doc, sharingDocumentId, linkDatabaseId);  // sets up the right sidebar collection for mobile upload documents and sharing
-            const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments }) =>
-                Docs.Create.FontIconDocument({
-                    icon,
-                    btnType: ButtonType.MenuButton,
-                    _stayInCollection: true,
-                    _hideContextMenu: true,
-                    system: true,
-                    dontUndo: true,
-                    title,
-                    target,
-                    _dropAction: "alias",
-                    _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
-                    _width: 60,
-                    _height: 60,
-                    watchedDocuments,
-                    onClick: ScriptField.MakeScript(click, { scriptContext: "any" })
-                }));
-            // hack -- last button is assumed to be the userDoc
-            menuBtns[menuBtns.length - 1].hidden = ComputedField.MakeFunction("IsNoviceMode()");
-
-            doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, {
-                title: "menuItemPanel",
-                childDropAction: "alias",
-                _chromeHidden: true,
-                dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-                ignoreClick: true,
-                _gridGap: 0,
-                _yMargin: 0,
-                _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true
-            }));
-        }
-        // this resets all sidebar buttons to being deactivated
-        PromiseValue(Cast(doc.menuStack, Doc)).then(stack => {
-            stack && PromiseValue(stack.data).then(btns => {
-                DocListCastAsync(btns).then(bts => bts?.forEach(btn => {
-                    btn.dontUndo = true;
-                    btn.system = true;
-                    if (btn.title === "Catalog" || btn.title === "My Files") { // migration from Catalog to My Files
-                        btn.target = Doc.UserDoc().myFilesystem;
-                        btn.title = "My Files";
-                    }
-                }));
-            });
-        });
-        return doc.menuStack as Doc;
-    }
-
-
-    // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu
-    static setupActiveMobileMenu(doc: Doc) {
-        if (doc.activeMobileMenu === undefined) {
-            doc.activeMobileMenu = this.setupMobileMenu();
-        }
-        return doc.activeMobileMenu as Doc;
-    }
-
-    // Sets up mobileMenu stacking document
-    static setupMobileMenu() {
-        const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), {
-            _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeHidden: true,
-        }));
-        return menu;
-    }
-
-    // SEts up mobile buttons for inside mobile menu
-    static setupMobileButtons(doc?: Doc, buttons?: string[]) {
-        const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [
-            { title: "DASHBOARDS", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Dashboards from your mobile, and navigate through all of your documents. " },
-            { title: "UPLOAD", icon: "upload", click: 'openMobileUploads()', backgroundColor: "lightgrey", info: "Upload files from your mobile device so they can be accessed on Dash Web." },
-            { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploadCollection()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." },
-            { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "lightgrey", info: "Use your phone to record, dictate and then upload audio onto Dash Web." },
-            { title: "PRESENTATION", icon: "desktop", click: 'switchToMobilePresentation()', backgroundColor: "lightgrey", info: "Use your phone as a remote for you presentation." },
-            { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "lightgrey", info: "Change your password, log out, or manage your account security." }
-        ];
-        // returns a list of mobile buttons
-        return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data =>
-            this.mobileButton({
-                title: data.title,
-                _lockedPosition: true,
-                onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
-                backgroundColor: data.backgroundColor, system: true
-            },
-                [this.ficon({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", btnType: ButtonType.ClickButton, system: true }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])])
-        );
-    }
-
-    // sets up the main document for the mobile button
-    static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, {
-        ...opts,
-        _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15,
-        borderRounding: "5px", boxShadow: "0 0", system: true
-    }) as any as Doc
-
-    // sets up the text container for the information contained within the mobile button
-    static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, {
-        ...opts,
-        _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25,
-        backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true
-    }) as any as Doc
-
-    // Sets up the title of the button
-    static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, {
-        ...opts,
-        title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true
-    }) as any as Doc
-
-    // Sets up the description of the button
-    static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, {
-        ...opts,
-        title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true
-    }) as any as Doc
-
-
-    static setupThumbButtons(doc: Doc) {
-        const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, pointerDown?: string, pointerUp?: string, clipboard?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
-            { title: "use pen", icon: "pen-nib", pointerUp: "resetPen()", pointerDown: 'setPen(2, this.backgroundColor)', backgroundColor: "blue" },
-            { title: "use highlighter", icon: "highlighter", pointerUp: "resetPen()", pointerDown: 'setPen(20, this.backgroundColor)', backgroundColor: "yellow" },
-            { title: "notepad", icon: "clipboard", pointerUp: "GestureOverlay.Instance.closeFloatingDoc()", pointerDown: 'GestureOverlay.Instance.openFloatingDoc(this.clipboard)', clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300, system: true }), backgroundColor: "orange" },
-            { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", backgroundColor: "orange" },
-            { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green" },
-        ];
-        return docProtoData.map(data => Docs.Create.FontIconDocument({
-            _nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, title: data.title, icon: data.icon,
-            _dropAction: data.pointerDown ? "copy" : undefined, ignoreClick: data.ignoreClick,
-            onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined,
-            clipboard: data.clipboard,
-            onPointerUp: data.pointerUp ? ScriptField.MakeScript(data.pointerUp) : undefined, onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined,
-            backgroundColor: data.backgroundColor,
-            _removeDropProperties: new List<string>(["dropAction"]), dragFactory: data.dragFactory, system: true
-        }));
-    }
-
-    static setupThumbDoc(userDoc: Doc) {
-        if (!userDoc.thumbDoc) {
-            const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), {
-                _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, title: "buttons",
-                _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white", system: true
-            });
-            thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], {
-                _width: 300, _height: 25, _autoHeight: true, linearViewIsExpanded: true, flexDirection: "column", system: true
-            });
-            userDoc.thumbDoc = thumbDoc;
-        }
-        return Cast(userDoc.thumbDoc, Doc);
-    }
-
-    static setupMobileInkingDoc(userDoc: Doc) {
-        return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", system: true });
-    }
-
-    static setupMobileUploadDoc(userDoc: Doc) {
-        // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" })
-        const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", {
-            title: "Upload Images From the Web", _lockedPosition: true, system: true
-        });
-        const uploadDoc = Docs.Create.StackingDocument([], {
-            title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeHidden: true,
-        });
-        return Docs.Create.StackingDocument([webDoc, uploadDoc], {
-            _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeHidden: true,
-        });
-    }
-
-    static setupLibrary(userDoc: Doc) {
-        return CurrentUserUtils.setupDashboards(userDoc);
-    }
-
-    // setup the Creator button which will display the creator panel.  This panel will include the drag creators and the color picker.
-    // when clicked, this panel will be displayed in the target container (ie, sidebarContainer)
-    static async setupToolsBtnPanel(doc: Doc) {
-        // setup a masonry view of all he creators
-        const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc);
-        const templateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
-
-        doc["tabs-button-tools"] = undefined;
-
-        if (doc.myCreators === undefined) {
-            doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], {
-                title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0, _fitWidth: true,
-                _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true, _chromeHidden: true,
-            }));
-        }
-        // setup a color picker
-        if (doc.myColorPicker === undefined) {
-            const color = Docs.Create.ColorDocument({
-                title: "color picker", ignoreClick: true, _width: 220, _dropAction: "alias", _hideContextMenu: true, _stayInCollection: true, _forceActive: true, _removeDropProperties: new List<string>(["dropAction", "_stayInCollection", "_hideContextMenu", "forceActive"]), system: true
-            });
-            doc.myColorPicker = new PrefetchProxy(color);
-        }
-
-        if (doc.myTools === undefined) {
-            const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
-                title: "My Tools", _showTitle: "title", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true,
-                system: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, boxShadow: "0 0",
-            })) as any as Doc;
-
-            doc.myTools = toolsStack;
-        }
-    }
-
-    static async setupDashboards(doc: Doc) {
-        // setup dashboards library item
-        await doc.myDashboards;
-        if (doc.myDashboards === undefined) {
-            doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                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
-            }));
-            const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`);
-            (doc.myDashboards as any as Doc).contextMenuScripts = new List<ScriptField>([newDashboard!]);
-            (doc.myDashboards as any as Doc).contextMenuLabels = new List<string>(["Create New Dashboard"]);
-        }
-        return doc.myDashboards as any as Doc;
-    }
-
-    static async setupPresentations(doc: Doc) {
-        await doc.myPresentations;
-        if (doc.myPresentations === undefined) {
-            doc.myPresentations = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                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
-            }));
-            const newPresentations = ScriptField.MakeScript(`createNewPresentation()`);
-            (doc.myPresentations as any as Doc).contextMenuScripts = new List<ScriptField>([newPresentations!]);
-            (doc.myPresentations as any as Doc).contextMenuLabels = new List<string>(["Create New Presentation"]);
-            const presentations = doc.myPresentations as any as Doc;
-        }
-        return doc.myPresentations as any as Doc;
-    }
-
-    static async setupFilesystem(doc: Doc) {
-        await doc.myFilesystem;
-        if (doc.myFilesystem === undefined) {
-            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", _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,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true
-            }));
-        }
-        return doc.myFilesystem as any as Doc;
-    }
-
-    static setupRecentlyClosedDocs(doc: Doc) {
-        // setup Recently Closed library item
-        if (doc.myRecentlyClosedDocs === undefined) {
-            doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                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
-            }));
-            const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
-            (doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
-            (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Clear All"]);
-        }
-    }
-    static setupFilterDocs(doc: Doc) {
-        // setup Filter item
-        if (doc.currentFilter === undefined) {
-            doc.currentFilter = Docs.Create.FilterDocument({
-                title: "unnamed filter", _height: 150,
-                treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none",
-                treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true
-            });
-            const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
-            (doc.currentFilter as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
-            (doc.currentFilter as Doc).contextMenuLabels = new List<string>(["Clear All"]);
-            (doc.currentFilter as Doc).filterBoolean = "AND";
-        }
-    }
-
-    static setupUserDoc(doc: Doc) {
-        if (doc.myUserDoc === undefined) {
-            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", _showTitle: "title",
-                treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
-            })) as any as Doc;
-        }
-    }
-
-    static setupSidebarContainer(doc: Doc) {
-        if (doc.sidebar === undefined) {
-            const sidebarContainer = new Doc();
-            sidebarContainer.system = true;
-            doc.sidebar = new PrefetchProxy(sidebarContainer);
-        }
-        return doc.sidebar as Doc;
-    }
-
-    // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
-    static async setupSidebarButtons(doc: Doc) {
-        CurrentUserUtils.setupSidebarContainer(doc);
-        await CurrentUserUtils.setupToolsBtnPanel(doc);
-        CurrentUserUtils.setupImportSidebar(doc);
-        CurrentUserUtils.setupDashboards(doc);
-        CurrentUserUtils.setupPresentations(doc);
-        CurrentUserUtils.setupFilesystem(doc);
-        CurrentUserUtils.setupRecentlyClosedDocs(doc);
-        // CurrentUserUtils.setupFilterDocs(doc);
-        CurrentUserUtils.setupUserDoc(doc);
-    }
-
-    static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
-        ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _width: 100, boxShadow: "0 0", _forceActive: true,
-        dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-        _lockedPosition: true, linearViewIsExpanded: true, system: true
-    })) as any as Doc
-
-    static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
-        ...opts, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
-    })) as any as Doc
-
-    /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
-    static setupDockedButtons(doc: Doc) {
-        if (doc["dockedBtn-undo"] === undefined) {
-            doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), btnType: ButtonType.ClickButton, dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "Undo", icon: "undo-alt", system: true, canClick: 'canUndo' });
-        }
-        if (doc["dockedBtn-redo"] === undefined) {
-            doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), btnType: ButtonType.ClickButton, dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "Redo", icon: "redo-alt", system: true, canClick: 'canRedo' });
-        }
-        if (doc.dockedBtns === undefined) {
-            doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true, linearViewExpandable: true, _height: 42 }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
-        }
-        (doc["dockedBtn-undo"] as Doc).dontUndo = true;
-        (doc["dockedBtn-redo"] as Doc).dontUndo = true;
-    }
-
-    static textTools(doc: Doc) {
-        return [
-            {
-                title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
-                list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
-                    "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
-                scriptDoc: Doc.UserDoc(), toggle: 'userDoc._fontFamily'
-            },
-            {
-                title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", click: 'toggleBold()',
-                scriptDoc: Doc.UserDoc(),
-                toggle: 'userDoc._boldActive'
-            },
-            { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", click: 'toggleItalic()', scriptDoc: Doc.UserDoc(), toggle: 'userDoc._italicsActive' },
-            { title: "Underline", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", click: 'toggleUnderline()', scriptDoc: Doc.UserDoc(), toggle: 'userDoc._underlineActive' },
-            // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()', toggle: 'userDoc._underlineActive' },
-            // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()', toggle: 'userDoc._underlineActive' },
-            // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()', toggle: 'userDoc._underlineActive' },
-            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._highlightColor' },
-            { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "fill-drip", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._textColor' },
-            // { title: "Link", tooltip: "Link", btnType: ButtonType.DropdownButton, icon: "link", click: '', ignoreClick: true },
-        ];
-    }
-
-    static async contextMenuBtnDescriptions(doc: Doc) {
-        return [
-            // { title: "Perspective", tooltip: "Change document's perspective", type: "btn", btnType: ButtonType.DropdownButton, ignoreClick: true, icon: "desktop", click: '' },
-            {
-                title: "Perspective", toolTip: "Perspective", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
-                list: [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Tree,
-                CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn,
-                CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel,
-                CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map,
-                CollectionViewType.Grid],
-                scriptDoc: 'selectedDoc',
-                toggle: 'selectedDoc._viewType'
-            },
-            {
-                title: "Background", toolTip: "Background", btnType: ButtonType.ColorButton, scriptDoc: 'selectedDoc',
-                docColorBtn: 'selectedDoc.backgroundColor', width: 60, ignoreClick: true, icon: "fill-drip",
-                canClick: 'numSelected > 0'
-            },
-            { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()', toggle: 'selectedDoc.z', canClick: 'numSelected > 0' },
-            { title: "Text Tools", type: "TextMenu", icon: "font" },
-            // { title: "Ink Tools", type: "LinearMenu", icon: "pen-nib" },
-            // { title: "GFX Tools", type: "LinearMenu", icon: "shapes" },
-            // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy" },
-        ];
-    }
-
-    // Default context menu buttons
-    static async setupContextMenuButtons(doc: Doc) {
-        const docList: Doc[] = [];
-
-        const contextMenuBtns = (await CurrentUserUtils.contextMenuBtnDescriptions(doc)).map(({ title, width, toolTip, ignoreClick, icon, type, btnType, click, toggle, scriptDoc, canClick, docColorBtn }) => {
-            const textDocList: Doc[] = [];
-            if (type === "TextMenu") {
-                const textBtns = (CurrentUserUtils.textTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, btnType, click, toggle, scriptDoc, userColorBtn }) => {
-                    textDocList.push(Docs.Create.FontIconDocument({
-                        _nativeWidth: width ? width : 25,
-                        _nativeHeight: 25,
-                        _width: width ? width : 25,
-                        _height: 25,
-                        icon,
-                        toolTip,
-                        userColorBtn,
-                        // testToggle: toggle ? ScriptField.MakeScript(toggle, { this: scriptDoc, scriptContext: "any" }) : undefined,
-                        // toggle: toggle,
-                        btnType: btnType,
-                        btnList: new List<string>(list),
-                        ignoreClick: ignoreClick,
-                        _stayInCollection: true,
-                        _hideContextMenu: true,
-                        system: true,
-                        dontUndo: true,
-                        title,
-                        backgroundColor: "black",
-                        _dropAction: "alias",
-                        _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
-                        onClick: click ? ScriptField.MakeScript(click, { scriptContext: "any" }) : undefined
-                    }));
-                });
-                docList.push(CurrentUserUtils.blist({ ignoreClick: true, linearViewExpandable: true, _height: 30, backgroundColor: "transparent" }, textDocList));
-            } else {
-                docList.push(Docs.Create.FontIconDocument({
-                    _nativeWidth: width ? width : 30,
-                    _nativeHeight: 30,
-                    _width: width ? width : 30,
-                    _height: 30,
-                    icon,
-                    toolTip,
-                    // testToggle: toggle ? ScriptField.MakeScript(toggle, { scriptContext: "any" }) : undefined,
-                    // toggle: toggle,
-                    docColorBtn,
-                    canClick: canClick,
-                    btnType: btnType,
-                    ignoreClick: ignoreClick,
-                    _stayInCollection: true,
-                    _hideContextMenu: true,
-                    system: true,
-                    dontUndo: true,
-                    title,
-                    backgroundColor: "black",
-                    _dropAction: "alias",
-                    _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
-                    onClick: click ? ScriptField.MakeScript(click, { scriptContext: "any" }) : undefined
-                }));
-            }
-        });
-
-        if (doc.contextMenuBtns === undefined) {
-            doc.contextMenuBtns = CurrentUserUtils.blist({ title: "menu buttons", ignoreClick: true, linearViewExpandable: false, _height: 35 }, docList);
-        }
-    }
-
-    // sets up the default set of documents to be shown in the Overlay layer
-    static setupOverlays(doc: Doc) {
-        if (doc.myOverlayDocs === undefined) {
-            doc.myOverlayDocs = new PrefetchProxy(Docs.Create.FreeformDocument([], { title: "overlay documents", backgroundColor: "#aca3a6", system: true }));
-        }
-    }
-
-    // the initial presentation Doc to use
-    static setupDefaultPresentation(doc: Doc) {
-        if (doc["template-presentation"] === undefined) {
-            doc["template-presentation"] = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
-                title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _fitWidth: true, _height: 46, isTemplateDoc: true, isTemplateForField: "data", system: true
-            }));
-        }
-    }
-
-    // Sharing sidebar is where shared documents are contained
-    static async setupSharingSidebar(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
-        if (doc.myLinkDatabase === undefined) {
-            let linkDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(linkDatabaseId);
-            if (!linkDocs) {
-                linkDocs = new Doc(linkDatabaseId, true);
-                (linkDocs as Doc).author = Doc.CurrentUserEmail;
-                (linkDocs as Doc).data = new List<Doc>([]);
-                (linkDocs as Doc)["acl-Public"] = SharingPermissions.Add;
-            }
-            doc.myLinkDatabase = new PrefetchProxy(linkDocs);
-        }
-        if (doc.mySharedDocs === undefined) {
-            let sharedDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(sharingDocumentId + "outer");
-            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, boxShadow: "0 0",
-                }, sharingDocumentId + "outer", sharingDocumentId);
-                (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Add;
-            }
-            if (sharedDocs instanceof Doc) {
-                Doc.GetProto(sharedDocs).userColor = sharedDocs.userColor || "rgb(202, 202, 202)";
-            }
-            doc.mySharedDocs = new PrefetchProxy(sharedDocs);
-        }
-    }
-
-    // Import sidebar is where shared documents are contained
-    static setupImportSidebar(doc: Doc) {
-        if (doc.myImportDocs === undefined) {
-            doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
-                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()"), btnType: ButtonType.ClickButton, 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, _showTitle: "title", ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true, boxShadow: "0 0" }));
-        }
-    }
-
-    static setupClickEditorTemplates(doc: Doc) {
-        if (doc["clickFuncs-child"] === undefined) {
-            // to use this function, select it from the context menu of a collection.  then edit the onChildClick script.  Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection.  After that, clicking on any document in the initial collection will open it in the target
-            const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
-                "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ",
-                { thisContainer: Doc.name }), {
-                title: "Click to open in target", _width: 300, _height: 200,
-                targetScriptKey: "onChildClick", system: true
-            });
-
-            const openDetail = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
-                "openOnRight(self.doubleClickView)",
-                {}), { title: "Double click to open doubleClickView", _width: 300, _height: 200, targetScriptKey: "onChildDoubleClick", system: true });
-
-            doc["clickFuncs-child"] = Docs.Create.TreeDocument([openInTarget, openDetail], { title: "on Child Click function templates", system: true });
-        }
-        // this is equivalent to using PrefetchProxies to make sure all the childClickFuncs have been retrieved.
-        PromiseValue(Cast(doc["clickFuncs-child"], Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
-
-        if (doc.clickFuncs === undefined) {
-            const onClick = Docs.Create.ScriptingDocument(undefined, {
-                title: "onClick", "onClick-rawScript": "console.log('click')",
-                isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200, system: true
-            }, "onClick");
-            const onChildClick = Docs.Create.ScriptingDocument(undefined, {
-                title: "onChildClick", "onChildClick-rawScript": "console.log('child click')",
-                isTemplateDoc: true, isTemplateForField: "onChildClick", _width: 300, _height: 200, system: true
-            }, "onChildClick");
-            const onDoubleClick = Docs.Create.ScriptingDocument(undefined, {
-                title: "onDoubleClick", "onDoubleClick-rawScript": "console.log('double click')",
-                isTemplateDoc: true, isTemplateForField: "onDoubleClick", _width: 300, _height: 200, system: true
-            }, "onDoubleClick");
-            const onChildDoubleClick = Docs.Create.ScriptingDocument(undefined, {
-                title: "onChildDoubleClick", "onChildDoubleClick-rawScript": "console.log('child double click')",
-                isTemplateDoc: true, isTemplateForField: "onChildDoubleClick", _width: 300, _height: 200, system: true
-            }, "onChildDoubleClick");
-            const onCheckedClick = Docs.Create.ScriptingDocument(undefined, {
-                title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)",
-                "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true,
-                isTemplateForField: "onCheckedClick", _width: 300, _height: 200, system: true
-            }, "onCheckedClick");
-            doc.clickFuncs = Docs.Create.TreeDocument([onClick, onChildClick, onDoubleClick, onCheckedClick], { title: "onClick funcs", system: true });
-        }
-        PromiseValue(Cast(doc.clickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
-
-        return doc.clickFuncs as Doc;
-    }
-
-    static async updateUserDocument(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
-        if (!doc.globalGroupDatabase) doc.globalGroupDatabase = Docs.Prototypes.MainGroupDocument();
-        const groups = await DocListCastAsync((doc.globalGroupDatabase as Doc).data);
-        reaction(() => DateCast((doc.globalGroupDatabase as Doc)["data-lastModified"]),
-            async () => {
-                const groups = await DocListCastAsync((doc.globalGroupDatabase as Doc).data);
-                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.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");
-        doc.activeFillColor = StrCast(doc.activeFillColor, "");
-        doc.activeArrowStart = StrCast(doc.activeArrowStart, "");
-        doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "");
-        doc.activeDash = StrCast(doc.activeDash, "0");
-        doc.fontSize = StrCast(doc.fontSize, "12px");
-        doc.fontFamily = StrCast(doc.fontFamily, "Arial");
-        doc.fontColor = StrCast(doc.fontColor, "black");
-        doc.fontHighlight = StrCast(doc.fontHighlight, "");
-        doc.defaultAclPrivate = BoolCast(doc.defaultAclPrivate, true);
-        doc.activeCollectionBackground = StrCast(doc.activeCollectionBackground, "white");
-        doc.activeCollectionNestedBackground = Cast(doc.activeCollectionNestedBackground, "string", null);
-        doc.noviceMode = BoolCast(doc.noviceMode, true);
-        doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
-        doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
-        Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]);
-        doc.savedFilters = new List<Doc>();
-        doc.filterDocCount = 0;
-        this.setupDefaultIconTemplates(doc);  // creates a set of icon templates triggered by the document deoration icon
-        this.setupDocTemplates(doc); // sets up the template menu of templates
-        this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
-        this.setupSearchPanel(doc);
-        this.setupOverlays(doc);  // documents in overlay layer
-        this.setupDockedButtons(doc);  // the bottom bar of font icons
-        this.setupContextMenuButtons(doc); //buttons for context menu
-        await this.setupSidebarButtons(doc); // the pop-out left sidebar of tools/panels
-        await this.setupMenuPanel(doc, sharingDocumentId, linkDatabaseId);
-        if (!doc.globalScriptDatabase) doc.globalScriptDatabase = Docs.Prototypes.MainScriptDocument();
-
-        setTimeout(() => this.setupDefaultPresentation(doc), 0); // presentation that's initially triggered
-
-        // setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
-        // doc["dockedBtn-undo"] && reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(doc["dockedBtn-undo"] as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true });
-        // doc["dockedBtn-redo"] && reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(doc["dockedBtn-redo"] as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
-
-        // uncomment this to setup a default note style that uses the custom header layout
-        // PromiseValue(doc.emptyHeader).then(factory => {
-        //     if (Cast(doc.defaultTextLayout, Doc, null)?.version !== headerViewVersion) {
-        //         const deleg = Doc.delegateDragFactory(factory as Doc);
-        //         deleg.title = "header";
-        //         doc.defaultTextLayout = new PrefetchProxy(deleg);
-        //         Doc.AddDocToList(Cast(doc["template-notes"], Doc, null), "data", deleg);
-        //     }
-        // });
-        setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500);
-        doc.fieldInfos = await Docs.setupFieldInfos();
-        return doc;
-    }
-
-    public static async loadCurrentUser() {
-        return rp.get(Utils.prepend("/getCurrentUser")).then(async response => {
-            if (response) {
-                const result: { id: string, email: string, cacheDocumentIds: string } = JSON.parse(response);
-                Doc.CurrentUserEmail = result.email;
-                resolvedPorts = JSON.parse(await Networking.FetchFromServer("/resolvedPorts"));
-                DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, result.email);
-                result.cacheDocumentIds && (await DocServer.GetRefFields(result.cacheDocumentIds.split(";")));
-                return result;
-            } else {
-                throw new Error("There should be a user! Why does Dash think there isn't one?");
-            }
-        });
-    }
-
-    public static async loadUserDocument(id: string) {
-        this.curr_id = id;
-        await rp.get(Utils.prepend("/getUserDocumentIds")).then(ids => {
-            const { userDocumentId, sharingDocumentId, linkDatabaseId } = JSON.parse(ids);
-            if (userDocumentId !== "guest") {
-                return DocServer.GetRefField(userDocumentId).then(async field => {
-                    Docs.newAccount = !(field instanceof Doc);
-                    await Docs.Prototypes.initialize();
-                    const userDoc = Docs.newAccount ? new Doc(userDocumentId, true) : field as Doc;
-                    const updated = this.updateUserDocument(Doc.SetUserDoc(userDoc), sharingDocumentId, linkDatabaseId);
-                    (await DocListCastAsync(Cast(Doc.UserDoc().myLinkDatabase, Doc, null)?.data))?.forEach(async link => { // make sure anchors are loaded to avoid incremental updates to computedFn's in LinkManager
-                        const a1 = await Cast(link?.anchor1, Doc, null);
-                        const a2 = await Cast(link?.anchor2, Doc, null);
-                    });
-                    return updated;
-                });
-            } else {
-                throw new Error("There should be a user id! Why does Dash think there isn't one?");
-            }
-        });
-    }
-
-    public static _urlState: HistoryUtil.DocUrl;
-
-    public static openDashboard = (userDoc: Doc, doc: Doc, fromHistory = false) => {
-        CurrentUserUtils.MainDocId = doc[Id];
-
-        if (doc) {  // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
-            !("presentationView" in doc) && (doc.presentationView = new List<Doc>([Docs.Create.TreeDocument([], { title: "Presentation" })]));
-            userDoc ? (userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc);
-        }
-        const state = CurrentUserUtils._urlState;
-        if (state.sharing === true && !userDoc) {
-            DocServer.Control.makeReadOnly();
-        } else {
-            fromHistory || HistoryUtil.pushState({
-                type: "doc",
-                docId: doc[Id],
-                readonly: state.readonly,
-                nro: state.nro,
-                sharing: false,
-            });
-            if (state.readonly === true || state.readonly === null) {
-                DocServer.Control.makeReadOnly();
-            } else if (state.safe) {
-                if (!state.nro) {
-                    DocServer.Control.makeReadOnly();
-                }
-                CollectionView.SetSafeMode(true);
-            } else if (state.nro || state.nro === null || state.readonly === false) {
-            } else if (doc.readOnly) {
-                DocServer.Control.makeReadOnly();
-            } else {
-                DocServer.Control.makeEditable();
-            }
-        }
-
-        return true;
-    }
-
-    public static importDocument = () => {
-        const input = document.createElement("input");
-        input.type = "file";
-        input.multiple = true;
-        input.accept = ".zip, application/pdf, video/*, image/*, audio/*";
-        input.onchange = async _e => {
-            const upload = Utils.prepend("/uploadDoc");
-            const formData = new FormData();
-            const file = input.files && input.files[0];
-            if (file && file.type === 'application/zip') {
-                formData.append('file', file);
-                formData.append('remap', "true");
-                const response = await fetch(upload, { method: "POST", body: formData });
-                const json = await response.json();
-                if (json !== "error") {
-                    const doc = Docs.newAccount ? undefined : await DocServer.GetRefField(json);
-                    if (doc instanceof Doc) {
-                        setTimeout(() => SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs =>
-                            docs.docs.forEach(d => LinkManager.Instance.addLink(d))), 2000); // need to give solr some time to update so that this query will find any link docs we've added.
-                    }
-                }
-            } else if (input.files && input.files.length !== 0) {
-                const importDocs = Cast(Doc.UserDoc().myImportDocs, Doc, null);
-                const disposer = OverlayView.ShowSpinner();
-                DocListCastAsync(importDocs.data).then(async list => {
-                    const results = await DocUtils.uploadFilesToDocs(Array.from(input.files || []), {});
-                    if (results.length !== input.files?.length) {
-                        alert("Error uploading files - possibly due to unsupported file types");
-                    }
-                    list?.splice(0, 0, ...results);
-                    disposer();
-                });
-            } else {
-                console.log("No file selected");
-            }
-        };
-        input.click();
-    }
-
-    public static async snapshotDashboard(userDoc: Doc) {
-        const copy = await CollectionDockingView.Copy(CurrentUserUtils.ActiveDashboard);
-        Doc.AddDocToList(Cast(userDoc.myDashboards, Doc, null), "data", copy);
-        CurrentUserUtils.openDashboard(userDoc, copy);
-    }
-
-    public static createNewDashboard = async (userDoc: Doc, id?: string) => {
-        const myPresentations = await userDoc.myPresentations as Doc;
-        const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true);
-        const dashboards = await Cast(userDoc.myDashboards, Doc) as Doc;
-        const dashboardCount = DocListCast(dashboards.data).length + 1;
-        const emptyPane = Cast(userDoc.emptyPane, Doc, null);
-        emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
-        const freeformOptions: DocumentOptions = {
-            x: 0,
-            y: 400,
-            _width: 1500,
-            _height: 1000,
-            _fitWidth: true,
-            title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
-        };
-        const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
-        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(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`);
-        const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
-        const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`);
-        const createDashboard = ScriptField.MakeScript(`createNewDashboard()`);
-        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, snapshotDashboard!, createDashboard!]);
-        dashboardDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Create Dashboard"]);
-
-        Doc.AddDocToList(dashboards, "data", dashboardDoc);
-        CurrentUserUtils.openDashboard(userDoc, dashboardDoc);
-    }
-
-    public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number) {
-        const tbox = Docs.Create.TextDocument("", {
-            _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight,
-            _width: width || 200, _height: height || 100, x: x, y: y, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
-            _fontFamily: StrCast(Doc.UserDoc().fontFamily), title
-        });
-        const template = Doc.UserDoc().defaultTextLayout;
-        if (template instanceof Doc) {
-            tbox._width = NumCast(template._width);
-            tbox.layoutKey = "layout_" + StrCast(template.title);
-            Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template;
-        }
-        return tbox;
-    }
-
-    public static get MySearchPanelDoc() { return Cast(Doc.UserDoc().mySearchPanelDoc, Doc, null); }
-    public static get ActiveDashboard() { return Cast(Doc.UserDoc().activeDashboard, Doc, null); }
-    public static get ActivePresentation() { return Cast(Doc.UserDoc().activePresentation, Doc, null); }
-    public static get MyRecentlyClosed() { return Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc, null); }
-    public static get MyDashboards() { return Cast(Doc.UserDoc().myDashboards, Doc, null); }
-    public static get EmptyPane() { return Cast(Doc.UserDoc().emptyPane, Doc, null); }
-    public static get OverlayDocs() { return DocListCast((Doc.UserDoc().myOverlayDocs as Doc)?.data); }
-    public static set SelectedTool(tool: InkTool) { Doc.UserDoc().activeInkTool = tool; }
-    @computed public static get SelectedTool(): InkTool { return StrCast(Doc.UserDoc().activeInkTool, InkTool.None) as InkTool; }
-}
-
-Scripting.addGlobal(function openDragFactory(dragFactory: Doc) {
-    const copy = Doc.copyDragFactory(dragFactory);
-    if (copy) {
-        CollectionDockingView.AddSplit(copy, "right");
-        const view = DocumentManager.Instance.getFirstDocumentView(copy);
-        view && SelectionManager.SelectView(view, false);
-    }
-});
-Scripting.addGlobal(function IsNoviceMode() { return Doc.UserDoc().noviceMode; },
-    "is Dash in novice mode");
-Scripting.addGlobal(function snapshotDashboard() { CurrentUserUtils.snapshotDashboard(Doc.UserDoc()); },
-    "creates a snapshot copy of a dashboard");
-Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.createNewDashboard(Doc.UserDoc()); },
-    "creates a new dashboard when called");
-Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); },
-    "creates a new presentation when called");
-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");
\ No newline at end of file
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 5f09a322c..5640e5132 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -27,6 +27,7 @@ import React = require("react");
 import { PresBox } from './nodes/trails/PresBox';
 import { undoBatch } from '../util/UndoManager';
 import { CollectionViewType } from './collections/CollectionView';
+import { Colors } from './global/globalEnums';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -187,9 +188,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
     get followLinkButton() {
         const targetDoc = this.view0?.props.Document;
         return !targetDoc ? (null) : <Tooltip title={
-            <div className="dash-tooltip">{"follow primary link on click"}</div>}>
+            <div className="dash-tooltip">{"Set onClick to follow primary link"}</div>}>
             <div className="documentButtonBar-icon"
-                style={{ color: targetDoc.isLinkButton ? "black" : "white" }}
+                style={{ backgroundColor: targetDoc.isLinkButton ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: targetDoc.isLinkButton ? Colors.BLACK : Colors.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>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 55af4650f..1f36e94cf 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -1284,3 +1284,4 @@ Scripting.addGlobal(function gotoFrame(doc: any, newFrame: any) {
     CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
     doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame);
 });
+
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
index db39e304b..9c766e03f 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
@@ -6,11 +6,12 @@
     height: 100%;
     pointer-events: none;
     // background-color: rgba(0, 0, 0, 0.2);
-    border-radius: 5px;
-    padding-left: 5px;
-    padding-right: 5px;
-    border-left: $standard-border;
-    border-right: $standard-border;
+    
+    &.true {
+        padding-left: 5px;
+        padding-right: 5px;
+        border-left: $standard-border;
+    }
 
     .collectionLinearView {
         display: flex;
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
index e7970758a..a8846fd45 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
@@ -119,7 +119,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
             <p>{BoolCast(this.layoutDoc.linearViewIsExpanded) ? icon ? icon : "–" : icon ? icon : "+"}</p>
         </label>;
 
-        return <div className="collectionLinearView-outer">
+        return <div className={`collectionLinearView-outer ${this.layoutDoc.linearViewSubMenu}`}>
             <div className="collectionLinearView" ref={this.createDashEventsTarget} >
                 {!expandable ? (null) : <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top">
                     {menuOpener}
diff --git a/src/client/views/nodes/button/ButtonScripts.ts b/src/client/views/nodes/button/ButtonScripts.ts
new file mode 100644
index 000000000..bb4dd8bc9
--- /dev/null
+++ b/src/client/views/nodes/button/ButtonScripts.ts
@@ -0,0 +1,14 @@
+import { Scripting } from "../../../util/Scripting";
+import { SelectionManager } from "../../../util/SelectionManager";
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeView(view: string) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function toggleOverlay() {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("failed");
+});
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index 0c866988d..72fab74d9 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -43,6 +43,11 @@
 
     &.tglBtn {
         cursor: pointer;
+
+        svg {
+            width: 50% !important;
+            height: 50%;
+        }
     }
 
     &.toolBtn {
@@ -99,6 +104,8 @@
         overflow: hidden;
         cursor: pointer;
         background: transparent;
+        align-content: center;
+        align-items: center;
 
         .menuButton-dropdownList {
             position: absolute;
@@ -145,6 +152,39 @@
         }
     }
 
+    .menuButton-dropdown {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 15px;
+        /* background-color: #b9b9b9; */
+        grid-column: 2;
+        border-radius: 0px 7px 7px 0px;
+        /* position: absolute; */
+        width: 13px;
+        height: 100%;
+        right: 0;
+    }
+
+    .menuButton-dropdown-header{
+        width: 100%;
+        font-weight: 300;
+        overflow:hidden;
+        font-size: 12px;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+    }
+
+    .dropbox-background {
+        width: 100vw;
+        height: 100vh;
+        top: 0;
+        z-index: 20;
+        left: 0;
+        background:transparent;
+        position: fixed;
+    }
+
 }
 
 
@@ -186,31 +226,11 @@
 //         position: absolute;
 //     }
 
-//     .menuButton-dropdown {
-//         display: flex;
-//         justify-content: center;
-//         align-items: center;
-//         font-size: 15px;
-//         /* background-color: #b9b9b9; */
-//         grid-column: 2;
-//         border-radius: 0px 7px 7px 0px;
-//         /* position: absolute; */
-//         width: 13px;
-//         height: 100%;
-//         right: 0;
-//     }
+
 
 //     &:hover {
 //         background-color: $light-gray;
 //     }
 
-//     .dropbox-background {
-//         width: 100vw;
-//         height: 100vh;
-//         top: 0;
-//         z-index: 20;
-//         left: 0;
-//         background:transparent;
-//         position: fixed;
-//     }
+
 // }
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 9e7608dc3..9a54579dc 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -56,15 +56,12 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         }
     }
 
-
-
     // Determining UI Specs
     @observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
     @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
     @observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
     @observable private dropdownDirection: string = StrCast(this.rootDoc.dropDownDirection);
     @observable private buttonList: string[] = StrListCast(this.rootDoc.btnList);
-    @observable private activeFont: string = StrCast(Doc.UserDoc()._fontFamily);
     @observable private type = StrCast(this.rootDoc.btnType);
 
     /**
@@ -106,18 +103,185 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         );
     }
 
-    @undoBatch setColor = action((color: ColorState, docColor?: string, userColor?: string) => {
-        console.log(docColor, userColor);
-        if (docColor) {
-            const numSelected = SelectionManager.Views().length;
-            const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
-            eval(docColor);
+    /**
+     * Dropdown button
+     */
+     @computed get dropdownListButton() {
+        const active: string = StrCast(this.rootDoc.dropDownOpen);
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+        const script: string = StrCast(this.rootDoc.script);
+
+        let noviceList: string[] = [];
+        let text:string | undefined;
+        let dropdown = true;
+        let show = true;
+        let icon: IconProp = "caret-down";
+
+
+        if (script == 'changeView'){
+            const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+            if (selected && StrCast(selected.Document.type) == DocumentType.COL){
+                text = StrCast(selected.Document._viewType);
+            } else if (selected) {
+                dropdown = false;
+                text = StrCast(selected.Document.type);
+                icon = Doc.toIcon(selected.Document);
+            }
+            noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
+        } else if (script == 'changeFont') {
+            const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+            if (selected && StrCast(selected.Document.type) == DocumentType.RTF){
+                text = StrCast(selected.Document._fontFamily);
+            } else {
+                text = StrCast(Doc.UserDoc()._fontFamily);
+            }
+            noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
+            "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
+        } else {
+            show = false;
         }
-        else if (userColor) {
-            const userDoc = Doc.UserDoc();
-            eval(userColor);
+
+        const items = this.buttonList.map((value) => {
+            // console.log(value);
+            if (Doc.UserDoc().noviceMode && !noviceList.includes(value)){
+                return;
+            }
+            const click = () => {
+                const s =  ScriptField.MakeScript(script+'("'+value+'")');
+                if (s){
+                    // console.log(s.script);
+                    s.script.run().result;
+                }
+            }
+            return <div className="list-item" key={`${value}`} 
+                style={{ fontFamily: script == 'changeFont' ? value : undefined }}
+                onClick={click}>
+                {value[0].toUpperCase() + value.slice(1)}
+            </div>;
+        });
+        
+        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+        <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
+            {this.label}
+        </div>;
+        
+        return (
+            <div className={`menuButton ${this.type} ${active}`}
+                style={{ display: show ? undefined : "none", backgroundColor: this.rootDoc.dropDownOpen ? Colors.LIGHT_BLUE : backgroundColor, color: this.rootDoc.dropDownOpen ? Colors.BLACK : color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
+                <div className="menuButton-dropdown-header">
+                    {text && text[0].toUpperCase() + text.slice(1)}
+                </div>
+                {label}
+                <div
+                className="menuButton-dropDown"
+                    style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
+                    <FontAwesomeIcon icon={icon} color={color} size="sm" />
+                </div>
+                {this.rootDoc.dropDownOpen ?
+                    <div>
+                        <div className="menuButton-dropdownList"
+                            style={{ left: 0 }}>
+                            {items}
+                        </div>
+                        <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
+                    </div>
+                    : null}
+            </div>
+        );
+    }
+
+
+    @computed get rangeButton() {
+        return (
+            <div>
+
+            </div>
+        )
+    }
+
+    /**
+     * Colour button
+     */
+    @computed get colorButton() {
+        const active: string = StrCast(this.rootDoc.dropDownOpen);
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const numSelected = SelectionManager.Views().length;
+        const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
+        const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={selectedDoc ? selectedDoc._backgroundColor : backgroundColor}
+        presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+            '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+            '#FFFFFF', '#f1efeb', 'transparent']} />;
+        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+        <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
+            {this.label}
+        </div>;
+        const dropdownCaret = <div
+            className="menuButton-dropDown"
+            style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
+            <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
+        </div>;
+        const script: string = StrCast(this.rootDoc.script);
+        const click = (value: ColorState) => {
+            const hex: string = value.hex;
+            const s =  ScriptField.MakeScript(script+'("'+hex+'")');
+            if (s){
+                // console.log(s.script);
+                s.script.run().result;
+            }
         }
-    });
+        return (
+            <div className={`menuButton ${this.type} ${active}`}
+                style={{ display: selectedDoc ? undefined : "none", color: color, backgroundColor: selectedDoc ? selectedDoc._backgroundColor : backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
+                onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}
+                onPointerDown={e => e.stopPropagation()}>
+                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
+                {label}
+                {dropdownCaret}
+                {this.rootDoc.dropDownOpen ?
+                    <div>
+                        <div className="menuButton-dropdownBox"
+                            onPointerDown={e => e.stopPropagation()}
+                            onClick={e => e.stopPropagation()}
+                            style={{ left: 0 }}>
+                            {colorBox((color) => click(color))}
+                        </div>
+                        <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
+                    </div>
+                    : null}
+            </div>
+        );
+    }
+
+    @computed get toggleButton() {
+        const numSelected = SelectionManager.Views().length;
+        const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
+
+        const script: string = StrCast(this.rootDoc.script)+"(true)";
+        let toggleTrue: boolean | undefined = false;
+        if (script == 'toggleOverlay'){
+            toggleTrue = selectedDoc && BoolCast(selectedDoc.z);
+            console.log('toggleOverlay');
+        }
+        const boolResult = ScriptField.MakeScript(script)?.script.run().result;
+        // console.log(this.rootDoc.title, script, boolResult);
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        // const canClick: boolean = this.rootDoc.canClick ? eval(StrCast(this.rootDoc.canClick)) : false;
+        const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
+        <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
+            {this.label}
+        </div>;
+        return (
+            <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor: toggleTrue ? Colors.MEDIUM_BLUE : "transparent" }}>
+                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={toggleTrue ? Colors.LIGHT_GRAY : Colors.LIGHT_GRAY} />
+                {label}
+            </div>
+        )
+    }
 
 
 
@@ -151,13 +315,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
         const userDoc = Doc.UserDoc();
 
-        // Toggle and canClick properties as determined from the variable passed into the button doc
-        const toggle = this.rootDoc.toggle ? ScriptCast(this.rootDoc.toggle) : undefined;
-        const canClick: boolean = this.rootDoc.canClick ? eval(StrCast(this.rootDoc.canClick)) : false;
-        // if (toggle) {
-        //     console.log(StrCast(this.rootDoc.title), toggle);
-        //     toggle.script.run();
-        // }
+        
         const dark: boolean = Doc.UserDoc().colorScheme === ColorScheme.Dark;
 
         const active: string = StrCast(this.rootDoc.dropDownOpen);
@@ -169,111 +327,34 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
                 {this.label}
             </div>;
-        const dropdownCaret = <div
-            className="menuButton-dropDown"
-            style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
-            <FontAwesomeIcon icon={'caret-down'} color={"black"} size="sm" />
-        </div>;
-        const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(backgroundColor)}
-            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-                '#FFFFFF', '#f1efeb', 'transparent']} />;
-        const items = this.buttonList.map((value) => {
-            return <div className="list-item"
-                style={{ fontFamily: value }}
-                onClick={() => Doc.UserDoc()._fontFamily = value}>
-                {value}
-            </div>;
-        });
-
-        /**
-         * Menu Panel Button: menuBtn
-         * Dropdown Button: dropDownBtn
-         * doubleBtn
-        **/
-
-        // CODEDUMP: glr
-        // const presSize = type === ButtonType.MenuButton ? 30 : 25;
-        // const presTrailsIcon = <img src={`/assets/${"presTrails.png"}`}
-        //     style={{ width: presSize, height: presSize, filter: `invert(${this.color === "white" ? "100%" : "0%"})`, marginBottom: "5px" }} />;
-
+       
         // TODO:glr Add label of button type
-        let button = (
-            <>
-                {this.defaultButton}
-            </>
-        );
+        let button = this.defaultButton;
 
         switch (this.type) {
             case ButtonType.DropdownButton:
-                button = (
-                    <>
-                        {this.dropdownButton}
-                    </>
-                );
+                button = this.dropdownButton;
                 break;
             case ButtonType.DropdownList:
-                button = (
-                    <div className={`menuButton ${this.type} ${active}`}
-                        style={{ backgroundColor: this.rootDoc.dropDownOpen ? "#aeddf880" : backgroundColor, color: this.rootDoc.dropDownOpen ? "#1c5c96" : color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                        onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}>
-                        {toggle}
-                        {label}
-                        {dropdownCaret}
-                        {this.rootDoc.dropDownOpen ?
-                            <>
-                                <div className="menuButton-dropdownList"
-                                    style={{ left: 0 }}>
-                                    {items}
-                                </div>
-                                <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
-                            </>
-                            : null}
-                    </div>
-                );
+                button = this.dropdownListButton;
                 break;
             case ButtonType.ColorButton:
-                button = (
-                    <div className={`menuButton ${this.type} ${active}`}
-                        style={{ opacity: selectedDoc ? 1 : 0.5, color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                        onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen}
-                        onPointerDown={e => e.stopPropagation()}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
-                        {label}
-                        {dropdownCaret}
-                        {this.rootDoc.dropDownOpen ?
-                            <>
-                                <div className="menuButton-dropdownBox"
-                                    onPointerDown={e => e.stopPropagation()}
-                                    onClick={e => e.stopPropagation()}
-                                    style={{ left: 0 }}>
-                                    {colorBox((color) => this.setColor(color, StrCast(this.rootDoc.docColor), StrCast(this.rootDoc.userColor)))}
-                                </div>
-                                <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
-                            </>
-                            : null}
-                    </div>
-                );
+                button = this.colorButton;
                 break;
             case ButtonType.ToolButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ opacity: canClick ? 1 : 0.4, backgroundColor: backgroundColor, color: color }}>
+                    <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor: backgroundColor, color: color }}>
                         <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {label}
                     </div>
                 );
                 break;
             case ButtonType.ToggleButton:
-                button = (
-                    <div className={`menuButton ${this.type}`} style={{ opacity: canClick ? 1 : 0.4, backgroundColor: toggle ? backgroundColor : undefined }}>
-                        <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={toggle ? color : backgroundColor} />
-                        {label}
-                    </div>
-                );
+                button = this.toggleButton;
                 break;
             case ButtonType.ClickButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: canClick ? 1 : 0.4 }}>
+                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1 }}>
                         <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {label}
                     </div>
@@ -299,9 +380,91 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
                 break;
         }
 
-        return !this.layoutDoc.toolTip ? button :
+        return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton ? button :
             <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
                 {button}
             </Tooltip>;
     }
 }
+
+// SCRIPTING BUTTONS
+
+import { Scripting } from "../../../util/Scripting";
+import { CollectionViewType } from '../../collections/CollectionView';
+import { DocumentType } from '../../../documents/DocumentTypes';
+import { Colors } from '../../global/globalEnums';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeView(view: string) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeBackgroundColor(color?: string, checkResult?: boolean) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    if (checkResult){
+        return selected && selected.Document._backgroundColor;
+    }
+    selected ? selected.Document._backgroundColor = color : console.log("[FontIconBox.tsx] changeBackgroundColor failed");
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function toggleOverlay(checkResult?:boolean) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    if (checkResult){
+        return selected && selected.Document.z == 1;
+    }
+    selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeFont(font: string) {
+    // TODO: glr check if font selected and change selected font
+    SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font);
+    console.log(font);
+    Doc.UserDoc()._fontFamily = font;
+    return Doc.UserDoc()._fontFamily;
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeFontColor(color: string) {
+    // TODO: glr check if font selected and change selected font
+    console.log(color);
+    Doc.UserDoc()._fontColor = color;
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeFontSize(size: string) {
+    // TODO: glr check if font selected and change selected font
+    console.log(size);
+    Doc.UserDoc()._fontSize = size;
+});
+
+Scripting.addGlobal(function toggleBold(checkResult?:boolean) {
+    if(checkResult) {
+        console.log("got here");
+        return Doc.UserDoc().bold;
+    }
+    // TODO: glr check if font selected and change selected font
+    SelectionManager.Views().map(dv => dv.props.Document.bold = !dv.props.Document.bold);
+    Doc.UserDoc().bold = !Doc.UserDoc().bold;
+    return Doc.UserDoc().bold;
+});
+
+Scripting.addGlobal(function toggleUnderline(checkResult?:boolean) {
+    if(checkResult) return Doc.UserDoc().underline;
+    // TODO: glr check if font selected and change selected font
+    SelectionManager.Views().map(dv => dv.props.Document.underline = !dv.props.Document.underline);
+    Doc.UserDoc().bold = !Doc.UserDoc().underline;
+    return Doc.UserDoc().underline;
+});
+
+Scripting.addGlobal(function toggleItalic(checkResult?:boolean) {
+    if(checkResult) return Doc.UserDoc().italic;
+    // TODO: glr check if font selected and change selected font
+    SelectionManager.Views().map(dv => dv.props.Document.italic = !dv.props.Document.italic);
+    Doc.UserDoc().bold = !Doc.UserDoc().italic;
+    return Doc.UserDoc().italic;
+});
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 0eede4546f2ddc862a42a43e0daa1fc02dfe6cae Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Fri, 20 Aug 2021 13:05:04 -0400
Subject: more updates

---
 src/client/documents/Documents.ts                  |  3 ++-
 src/client/util/CurrentUserUtils.ts                | 14 +++++++-------
 src/client/views/DocumentDecorations.scss          |  6 +++++-
 src/client/views/collections/CollectionMenu.scss   |  8 ++++----
 src/client/views/collections/CollectionMenu.tsx    | 19 +++++++++++--------
 .../collectionLinearView/CollectionLinearView.scss | 13 +++++++------
 .../collectionLinearView/CollectionLinearView.tsx  | 16 +++++++++++-----
 src/client/views/global/globalCssVariables.scss    |  9 +++++++--
 src/client/views/global/globalEnums.tsx            |  1 +
 src/client/views/nodes/button/FontIconBox.scss     | 10 +++++-----
 src/client/views/topbar/TopBar.scss                | 22 ++++++++++++----------
 src/client/views/topbar/TopBar.tsx                 |  2 +-
 12 files changed, 73 insertions(+), 50 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f6b2e0736..b7ba6f1fe 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -230,6 +230,8 @@ export class DocumentOptions {
     linearViewExpandable?: boolean; // can linear view be expanded
     linearViewToggleButton?: string; // button to open close linear view group
     linearViewSubMenu?: boolean;
+    flexGap?: number; // Linear view flex gap
+    flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
 
     layout_linkView?: Doc; // view template for a link document
     layout_keyValue?: string; // view tempalte for key value docs
@@ -277,7 +279,6 @@ export class DocumentOptions {
     text?: string;
     textTransform?: string; // is linear view expanded
     letterSpacing?: string; // is linear view expanded
-    flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
     selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui
     clipboard?: Doc;
     searchQuery?: string; // for quersyBox
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 0440367de..0210b5a1d 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -892,10 +892,10 @@ export class CurrentUserUtils {
         CurrentUserUtils.setupUserDoc(doc);
     }
 
-    static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
-        ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _width: 100, boxShadow: "0 0", _forceActive: true,
+    static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
+        ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, boxShadow: "0 0", _forceActive: true,
         dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
-        _lockedPosition: true, linearViewIsExpanded: true, system: true
+        _lockedPosition: true, linearViewIsExpanded: true, system: true, flexDirection: "column"
     })) as any as Doc
 
     static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
@@ -911,7 +911,7 @@ export class CurrentUserUtils {
             doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true });
         }
         if (doc.dockedBtns === undefined) {
-            doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", linearViewExpandable: true, ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
+            doc.dockedBtns = CurrentUserUtils.linearButtonList({ title: "docked buttons", linearViewExpandable: true, ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
         }
         (doc["dockedBtn-undo"] as Doc).dontUndo = true;
         (doc["dockedBtn-redo"] as Doc).dontUndo = true;
@@ -1013,7 +1013,7 @@ export class CurrentUserUtils {
                         onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
                     }));
                 });
-                docList.push(CurrentUserUtils.blist({ linearViewSubMenu: true, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
+                docList.push(CurrentUserUtils.linearButtonList({ linearViewSubMenu: true, flexGap: 5, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
             } else if (type === "InkMenu") {
                 const inkBtns = (CurrentUserUtils.inkTools(doc)).map(({ title, toolTip, icon, btnType, click }) => {
                     textDocList.push(Docs.Create.FontIconDocument({
@@ -1039,7 +1039,7 @@ export class CurrentUserUtils {
                         onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
                     }));
                 });
-                docList.push(CurrentUserUtils.blist({ linearViewSubMenu: true, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
+                docList.push(CurrentUserUtils.linearButtonList({ linearViewSubMenu: true, flexGap: 5, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
             } else {
                 docList.push(Docs.Create.FontIconDocument({
                     _nativeWidth: width ? width : 25,
@@ -1067,7 +1067,7 @@ export class CurrentUserUtils {
         });
 
         if (doc.contextMenuBtns === undefined) {
-            doc.contextMenuBtns = CurrentUserUtils.blist({ title: "menu buttons", ignoreClick: true, linearViewExpandable: false, _height: 35 }, docList);
+            doc.contextMenuBtns = CurrentUserUtils.linearButtonList({ title: "menu buttons", flexGap: 0, ignoreClick: true, linearViewExpandable: false, _height: 35 }, docList);
         }
     }
     // sets up the default set of documents to be shown in the Overlay layer
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 316f63240..d34efd01a 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -51,6 +51,7 @@ $linkGap : 3px;
         pointer-events: auto;
         background: $medium-gray;
         opacity: 0.1;
+
         &:hover {
             opacity: 1;
         }
@@ -94,6 +95,7 @@ $linkGap : 3px;
             position: absolute;
         }
     }
+
     .documentDecorations-rotation {
         background: transparent;
         right: -15;
@@ -189,6 +191,7 @@ $linkGap : 3px;
         margin-left: 5px;
         height: 22px;
         position: absolute;
+
         .documentDecorations-titleSpan {
             width: 100%;
             border-radius: 8px;
@@ -263,7 +266,7 @@ $linkGap : 3px;
 }
 
 .link-button-container {
-    border-radius: 10px;
+    border-radius: 13px;
     width: max-content;
     height: auto;
     display: flex;
@@ -338,6 +341,7 @@ $linkGap : 3px;
 .documentdecorations-icon {
     margin: 0px;
 }
+
 .templating-button,
 .docDecs-tagButton {
     width: 20px;
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 163566d22..c35f088a6 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -14,8 +14,8 @@
     .collectionMenu-hardCodedButton {
         cursor: pointer;
         color: $white;
-        width: 31.5px;
-        height: 90%;
+        width: 25px;
+        height: 25px;
         padding: 5;
         text-align: center;
         display: flex;
@@ -23,10 +23,10 @@
         align-items: center;
         position: relative;
         transition: 0.2s;
+        border-radius: 3px;
 
         &:hover {
-            border-radius:5px;
-            background-color: rgba(0,0,0,0.2);
+            background-color: rgba(0, 0, 0, 0.2);
         }
     }
 }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 1f36e94cf..77e5132fc 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -40,6 +40,7 @@ import { CollectionLinearView } from "./CollectionLinearView";
 import "./CollectionMenu.scss";
 import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
+import { Colors } from "../global/globalEnums";
 
 @observer
 export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -135,7 +136,9 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
         const propTitle = CurrentUserUtils.propertiesWidth > 0 ? "Close Properties Panel" : "Open Properties Panel";
 
         const prop = <Tooltip title={<div className="dash-tooltip">{propTitle}</div>} key="properties" placement="bottom">
-            <div className="collectionMenu-hardCodedButton" key="properties"
+            <div className="collectionMenu-hardCodedButton"
+                style={{ backgroundColor: CurrentUserUtils.propertiesWidth > 0 ? Colors.MEDIUM_BLUE : undefined }}
+                key="properties"
                 onPointerDown={this.toggleProperties}>
                 <FontAwesomeIcon icon={propIcon} size="lg" />
             </div>
@@ -143,11 +146,11 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
 
         // NEW BUTTONS
         //dash col linear view buttons
-        const contMenuButtons = 
-        <div className="collectionMenu-container">
-            {this.contMenuButtons}
-            {prop}
-        </div>;
+        const contMenuButtons =
+            <div className="collectionMenu-container">
+                {this.contMenuButtons}
+                {prop}
+            </div>;
 
         return contMenuButtons;
 
@@ -779,7 +782,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                             onPointerDown={action(() => { SetActiveInkWidth(wid); this._widthBtn = false; this.editProperties(wid, "width"); })}
                             style={{ backgroundColor: this._widthBtn ? "121212" : "", zIndex: 1001, fontSize: this._dotsize[i], padding: 0, textAlign: "center" }}>
                             •
-                    </button>
+                        </button>
                     </Tooltip>)}
             </div>;
     }
@@ -1050,7 +1053,7 @@ export class CollectionTreeViewChrome extends React.Component<CollectionMenuProp
                 <button className="collectionTreeViewChrome-sort" onClick={this.toggleSort}>
                     <div className="collectionTreeViewChrome-sortLabel">
                         Sort
-                        </div>
+                    </div>
                     <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.ascending === undefined ? "90" : this.ascending ? "180" : "0"}deg)` }}>
                         <FontAwesomeIcon icon="caret-up" size="2x" color="white" />
                     </div>
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
index 2b3f8f2c9..44752e034 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
@@ -5,12 +5,12 @@
     overflow: visible;
     height: 100%;
     pointer-events: none;
-    
+
     &.true {
         padding-left: 5px;
         padding-right: 5px;
         border-left: $standard-border;
-        background-color: #4476f73d;
+        background-color: $medium-blue-alt;
     }
 
     >input:not(:checked)~&.true {
@@ -21,8 +21,9 @@
         display: flex;
         height: 100%;
         align-items: center;
+        gap: 5px;
 
-        .collectionView{
+        .collectionView {
             overflow: visible !important;
         }
 
@@ -56,7 +57,7 @@
         }
 
         .bottomPopup-descriptions {
-            cursor:pointer;
+            cursor: pointer;
             display: inline;
             white-space: nowrap;
             padding-left: 8px;
@@ -69,7 +70,7 @@
         }
 
         .bottomPopup-exit {
-            cursor:pointer;
+            cursor: pointer;
             display: inline;
             white-space: nowrap;
             margin-right: 10px;
@@ -97,7 +98,7 @@
             transition: transform 0.2s;
             align-items: center;
             justify-content: center;
-            transition:0.1s;
+            transition: 0.1s;
 
             &:hover {
                 transform: scale(1.05);
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
index 3327bef36..713d93f97 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
@@ -108,12 +108,13 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
     }
 
     render() {
-        const guid = Utils.GenerateGuid();
-        const flexDir: any = StrCast(this.Document.flexDirection);
-        const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable);
+        const guid = Utils.GenerateGuid(); // Generate a unique ID to use as the label
+        const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content
+        const flexGap: number = NumCast(this.Document.flexGap); // Specify the gap between linear view content
+        const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable); // Specify whether it is expandable or not
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const icon: string = StrCast(this.props.Document.icon);
+        const icon: string = StrCast(this.props.Document.icon); // Menu opener toggle
 
         const menuOpener = <label htmlFor={`${guid}`}
             style={{
@@ -134,7 +135,12 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                 <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
                     onChange={action(() => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
 
-                <div className="collectionLinearView-content" style={{ height: this.dimension(), flexDirection: flexDir }}>
+                <div className="collectionLinearView-content"
+                    style={{
+                        height: this.dimension(),
+                        flexDirection: flexDir,
+                        gap: flexGap
+                    }}>
                     {this.childLayoutPairs.map((pair, ind) => {
                         const nested = pair.layout._viewType === CollectionViewType.Linear;
                         const dref = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index 7556f8b8a..a1baed7d9 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -8,6 +8,7 @@ $black: #000000;
 
 $light-blue: #bdddf5;
 $medium-blue: #4476f7;
+$medium-blue-alt: #4476f73d;
 $pink: #e0217d;
 $yellow: #f5d747;
 
@@ -24,7 +25,8 @@ $large-padding: 32px;
 $icon-size: 28px;
 
 // fonts
-$sans-serif: "Roboto", sans-serif;
+$sans-serif: "Roboto",
+sans-serif;
 $large-header: 16px;
 $body-text: 12px;
 $small-text: 9px;
@@ -43,6 +45,9 @@ $radialMenu-zindex: 100000; // context menu shows up over everything
 // borders
 $standard-border: solid 1px #9f9f9f;
 
+// border radius
+$standard-border-radius: 3px;
+
 $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
@@ -67,4 +72,4 @@ $TREE_BULLET_WIDTH: 20px;
     DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM;
     MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH;
     TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH;
-}
+}
\ No newline at end of file
diff --git a/src/client/views/global/globalEnums.tsx b/src/client/views/global/globalEnums.tsx
index 2aeb8e338..074a3aab3 100644
--- a/src/client/views/global/globalEnums.tsx
+++ b/src/client/views/global/globalEnums.tsx
@@ -5,6 +5,7 @@ export enum Colors {
     LIGHT_GRAY = "#DFDFDF",
     WHITE = "#FFFFFF",
     MEDIUM_BLUE = "#4476F7",
+    MEDIUM_BLUE_ALT = "#4476f73d", // REDUCED OPACITY
     LIGHT_BLUE = "#BDDDF5",
     PINK = "#E0217D",
     YELLOW = "#F5D747",
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index 8dfb66e30..f0ca43a09 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -6,10 +6,10 @@
     justify-content: center;
     align-items: center;
     font-size: 80%;
-    border-radius: 2px;
+    border-radius: $standard-border-radius;
 
     &:hover {
-        background-color: rgba(0,0,0,0.3) !important;
+        background-color: rgba(0, 0, 0, 0.3) !important;
     }
 
     .menuButton-wrap {
@@ -117,7 +117,7 @@
             top: 100%;
             z-index: 21;
             background-color: $white;
-            box-shadow: 0px 3px 4px rgba(0,0,0,0.3);
+            box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
             padding: 1px;
 
             .list-item {
@@ -170,7 +170,7 @@
         right: 0;
     }
 
-    .menuButton-dropdown-header{
+    .menuButton-dropdown-header {
         width: 100%;
         font-weight: 300;
         padding: 5px;
@@ -186,7 +186,7 @@
         top: 0;
         z-index: 20;
         left: 0;
-        background:transparent;
+        background: transparent;
         position: fixed;
     }
 
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index 2ecbb536b..d02a77fe4 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -22,7 +22,7 @@
 
         .topBar-icon {
             cursor: pointer;
-            font-size: 12px;
+            font-size: 12.5px;
             font-family: 'Roboto';
             width: fit-content;
             display: flex;
@@ -31,18 +31,20 @@
             align-items: center;
             justify-self: center;
             align-self: center;
-            border-radius: 5px;
+            border-radius: $standard-border-radius;
             padding: 5px;
             transition: linear 0.1s;
             color: $black;
             background-color: $light-gray;
-        }
 
-        .topBar-icon:hover {
-            background-color: $light-blue;
+            &:hover {
+                background-color: $light-blue;
+            }
         }
 
-        
+
+
+
         .topbar-center {
             grid-column: 2;
             display: inline-flex;
@@ -58,7 +60,7 @@
             .topbar-lozenge-dashboard {
                 display: flex;
 
-                    
+
 
                 .topbar-dashSelect {
                     border: none;
@@ -155,9 +157,9 @@
             }
 
             &.topbar-input {
-                margin:5px;
-                border-radius:20px;
-                border:$dark-gray;    
+                margin: 5px;
+                border-radius: 20px;
+                border: $dark-gray;
                 display: block;
                 width: 130px;
                 -webkit-transition: width 0.4s;
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 05edb975c..4dbd5e22c 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -28,7 +28,7 @@ export class TopBar extends React.Component {
                             {`${Doc.CurrentUserEmail}`}
                         </div>
                         <div className="topbar-icon" onClick={() => window.location.assign(Utils.prepend("/logout"))}>
-                            {"Sign out"}
+                            {"Log out"}
                         </div>
                     </div>
                     <div className="topbar-center" >
-- 
cgit v1.2.3-70-g09d2


From 22333b0776dae22dec7f1d18ee59f6878fec9e0a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 30 Aug 2021 13:53:23 -0400
Subject: fixed linear menu views to always have active content

---
 src/client/views/collections/CollectionMenu.tsx                         | 2 +-
 .../views/collections/collectionLinearView/CollectionLinearView.tsx     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index cbfe47338..3d37a9df8 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -107,7 +107,7 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
                 rootSelected={returnTrue}
                 bringToFront={emptyFunction}
                 select={emptyFunction}
-                isContentActive={returnFalse}
+                isContentActive={returnTrue}
                 isAnyChildContentActive={returnFalse}
                 isSelected={returnFalse}
                 docViewPath={returnEmptyDoclist}
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
index 74d581946..61fc366eb 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
@@ -162,7 +162,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                             <DocumentView
                                 Document={pair.layout}
                                 DataDoc={pair.data}
-                                isContentActive={returnFalse}
+                                isContentActive={this.props.isContentActive}
                                 isDocumentActive={returnTrue}
                                 addDocument={this.props.addDocument}
                                 moveDocument={this.props.moveDocument}
-- 
cgit v1.2.3-70-g09d2


From 40f3b73fef74c204c927e7715c73d021b98d7428 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 5 Sep 2021 15:09:42 -0400
Subject: changed direcotry from CollectionLinearView to collectionLinear

---
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/collections/CollectionMenu.tsx    |   2 +-
 src/client/views/collections/CollectionView.tsx    |   2 +-
 .../collectionLinear/CollectionLinearView.scss     | 150 ++++++++++++++
 .../collectionLinear/CollectionLinearView.tsx      | 222 +++++++++++++++++++++
 .../views/collections/collectionLinear/index.ts    |   1 +
 .../collectionLinearView/CollectionLinearView.scss | 150 --------------
 .../collectionLinearView/CollectionLinearView.tsx  | 222 ---------------------
 .../collections/collectionLinearView/index.ts      |   1 -
 9 files changed, 376 insertions(+), 376 deletions(-)
 create mode 100644 src/client/views/collections/collectionLinear/CollectionLinearView.scss
 create mode 100644 src/client/views/collections/collectionLinear/CollectionLinearView.tsx
 create mode 100644 src/client/views/collections/collectionLinear/index.ts
 delete mode 100644 src/client/views/collections/collectionLinearView/CollectionLinearView.scss
 delete mode 100644 src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
 delete mode 100644 src/client/views/collections/collectionLinearView/index.ts

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index dadf5b390..5c1a51052 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -32,7 +32,7 @@ import { Transform } from '../util/Transform';
 import { TimelineMenu } from './animationtimeline/TimelineMenu';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu';
-import { CollectionLinearView } from './collections/CollectionLinearView';
+import { CollectionLinearView } from './collections/collectionLinear';
 import { CollectionMenu } from './collections/CollectionMenu';
 import { CollectionViewType } from './collections/CollectionView';
 import "./collections/TreeView.scss";
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 3d37a9df8..86bf9ad41 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -36,7 +36,7 @@ import { RichTextMenu } from "../nodes/formattedText/RichTextMenu";
 import { PresBox } from "../nodes/trails/PresBox";
 import { DefaultStyleProvider } from "../StyleProvider";
 import { CollectionDockingView } from "./CollectionDockingView";
-import { CollectionLinearView } from "./CollectionLinearView";
+import { CollectionLinearView } from "./collectionLinear";
 import "./CollectionMenu.scss";
 import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 229e93b9e..81375e557 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -24,7 +24,7 @@ import { CollectionCarouselView } from './CollectionCarouselView';
 import { CollectionDockingView } from "./CollectionDockingView";
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionGridView } from './collectionGrid/CollectionGridView';
-import { CollectionLinearView } from './CollectionLinearView';
+import { CollectionLinearView } from './collectionLinear';
 import CollectionMapView from './CollectionMapView';
 import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView';
 import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.scss b/src/client/views/collections/collectionLinear/CollectionLinearView.scss
new file mode 100644
index 000000000..8fe804466
--- /dev/null
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.scss
@@ -0,0 +1,150 @@
+@import "../../global/globalCssVariables";
+@import "../../_nodeModuleOverrides";
+
+.collectionLinearView-outer {
+    overflow: visible;
+    height: 100%;
+    pointer-events: none;
+
+    &.true {
+        padding-left: 5px;
+        padding-right: 5px;
+        border-left: $standard-border;
+        background-color: $medium-blue-alt;
+    }
+
+    >input:not(:checked)~&.true {
+        background-color: transparent;
+    }
+
+    .collectionLinearView {
+        display: flex;
+        height: 100%;
+        align-items: center;
+        gap: 5px;
+
+        .collectionView {
+            overflow: visible !important;
+        }
+
+        >span {
+            background: $dark-gray;
+            color: $white;
+            border-radius: 18px;
+            margin-right: 6px;
+            cursor: pointer;
+        }
+
+        .bottomPopup-background {
+            background: $medium-blue;
+            display: flex;
+            border-radius: 10px;
+            height: 35;
+            transform: translate3d(6px, 0px, 0px);
+            align-content: center;
+            justify-content: center;
+            align-items: center;
+        }
+
+        .bottomPopup-text {
+            color: $white;
+            display: inline;
+            white-space: nowrap;
+            padding-left: 8px;
+            padding-right: 20px;
+            vertical-align: middle;
+            font-size: 12.5px;
+        }
+
+        .bottomPopup-descriptions {
+            cursor: pointer;
+            display: inline;
+            white-space: nowrap;
+            padding-left: 8px;
+            padding-right: 8px;
+            vertical-align: middle;
+            background-color: $light-gray;
+            border-radius: 3px;
+            color: black;
+            margin-right: 5px;
+        }
+
+        .bottomPopup-exit {
+            cursor: pointer;
+            display: inline;
+            white-space: nowrap;
+            margin-right: 10px;
+            padding-left: 8px;
+            padding-right: 8px;
+            vertical-align: middle;
+            background-color: $close-red;
+            border-radius: 3px;
+            color: black;
+        }
+
+        >label {
+            pointer-events: all;
+            cursor: pointer;
+            background-color: $medium-blue;
+            padding: 5;
+            border-radius: 2px;
+            height: 25;
+            min-width: 25;
+            margin: 0;
+            color: $white;
+            display: flex;
+            font-weight: 100;
+            width: fit-content;
+            transition: transform 0.2s;
+            align-items: center;
+            justify-content: center;
+            transition: 0.2s;
+
+            &:hover{
+                filter: brightness(0.85);
+            }
+        }
+
+        >input {
+            display: none;
+        }
+
+        >input:not(:checked)~.collectionLinearView-content {
+            display: none;
+        }
+
+        >input:checked~label {
+            transform: rotate(45deg);
+            transition: transform 0.5s;
+            cursor: pointer;
+        }
+
+        .collectionLinearView-content {
+            display: flex;
+            opacity: 1;
+            position: relative;
+
+            .collectionLinearView-docBtn,
+            .collectionLinearView-docBtn-scalable {
+                position: relative;
+                margin: auto;
+                transform-origin: center 80%;
+            }
+
+            .collectionLinearView-docBtn-scalable:hover {
+                transform: scale(1.15);
+            }
+
+            .collectionLinearView-round-button {
+                width: 18px;
+                height: 18px;
+                border-radius: 18px;
+                font-size: 15px;
+            }
+
+            .collectionLinearView-round-button:hover {
+                transform: scale(1.15);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
new file mode 100644
index 000000000..e78ca2a32
--- /dev/null
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -0,0 +1,222 @@
+import { Tooltip } from '@material-ui/core';
+import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
+import { documentSchema } from '../../../../fields/documentSchemas';
+import { Id } from '../../../../fields/FieldSymbols';
+import { makeInterface } from '../../../../fields/Schema';
+import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils';
+import { DragManager } from '../../../util/DragManager';
+import { Transform } from '../../../util/Transform';
+import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
+import { DocumentView } from '../../nodes/DocumentView';
+import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
+import { StyleProp } from '../../StyleProvider';
+import "./CollectionLinearView.scss";
+import { CollectionSubView } from '../CollectionSubView';
+import { CollectionViewType } from '../CollectionView';
+import { Colors, Shadows } from '../../global/globalEnums';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+
+type LinearDocument = makeInterface<[typeof documentSchema,]>;
+const LinearDocument = makeInterface(documentSchema);
+
+@observer
+export class CollectionLinearView extends CollectionSubView(LinearDocument) {
+    @observable public addMenuToggle = React.createRef<HTMLInputElement>();
+    @observable private _selectedIndex = -1;
+    private _dropDisposer?: DragManager.DragDropDisposer;
+    private _widthDisposer?: IReactionDisposer;
+    private _selectedDisposer?: IReactionDisposer;
+
+    componentWillUnmount() {
+        this._dropDisposer?.();
+        this._widthDisposer?.();
+        this._selectedDisposer?.();
+        this.childLayoutPairs.map((pair, ind) => ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
+    }
+
+    componentDidMount() {
+        this._widthDisposer = reaction(() => 5 + (this.layoutDoc.linearViewIsExpanded ? this.childDocs.length * (this.rootDoc[HeightSym]()) : 10),
+            width => this.childDocs.length && (this.layoutDoc._width = width),
+            { fireImmediately: true }
+        );
+
+        this._selectedDisposer = reaction(
+            () => NumCast(this.layoutDoc.selectedIndex),
+            (i) => runInAction(() => {
+                this._selectedIndex = i;
+                let selected: any = undefined;
+                this.childLayoutPairs.map(async (pair, ind) => {
+                    const isSelected = this._selectedIndex === ind;
+                    if (isSelected) {
+                        selected = pair;
+                    }
+                    else {
+                        ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log);
+                    }
+                });
+                if (selected && selected.layout) {
+                    ScriptCast(selected.layout.proto?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log);
+                }
+            }),
+            { fireImmediately: true }
+        );
+    }
+    protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+        this._dropDisposer && this._dropDisposer();
+        if (ele) {
+            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
+        }
+    }
+
+    dimension = () => NumCast(this.rootDoc._height); // 2 * the padding
+    getTransform = (ele: React.RefObject<HTMLDivElement>) => () => {
+        if (!ele.current) return Transform.Identity();
+        const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current);
+        return new Transform(-translateX, -translateY, 1);
+    }
+
+    @action
+    exitLongLinks = () => {
+        if (DocumentLinksButton.StartLink) {
+            if (DocumentLinksButton.StartLink.Document) {
+                action((e: React.PointerEvent<HTMLDivElement>) => {
+                    Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc);
+                });
+            }
+        }
+        DocumentLinksButton.StartLink = undefined;
+        DocumentLinksButton.StartLinkView = undefined;
+    }
+
+    @action
+    changeDescriptionSetting = () => {
+        if (LinkDescriptionPopup.showDescriptions) {
+            if (LinkDescriptionPopup.showDescriptions === "ON") {
+                LinkDescriptionPopup.showDescriptions = "OFF";
+                LinkDescriptionPopup.descriptionPopup = false;
+            } else {
+                LinkDescriptionPopup.showDescriptions = "ON";
+            }
+        } else {
+            LinkDescriptionPopup.showDescriptions = "OFF";
+            LinkDescriptionPopup.descriptionPopup = false;
+        }
+    }
+
+    myContextMenu = (e: React.MouseEvent) => {
+        console.log("STOPPING");
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    render() {
+        const guid = Utils.GenerateGuid(); // Generate a unique ID to use as the label
+        const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content
+        const flexGap: number = NumCast(this.Document.flexGap); // Specify the gap between linear view content
+        const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable); // Specify whether it is expandable or not
+        const floating: boolean = BoolCast(this.props.Document.linearViewFloating); // Specify whether it is expandable or not
+
+        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+        const icon: string = StrCast(this.props.Document.icon); // Menu opener toggle
+        const menuOpener = <label htmlFor={`${guid}`}
+            style={{
+                boxShadow: floating ? Shadows.STANDARD_SHADOW : undefined,
+                color: BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : Colors.BLACK,
+                backgroundColor: backgroundColor === color ? "black" : BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : Colors.LIGHT_GRAY
+            }}
+            onPointerDown={e => e.stopPropagation()} >
+            <div className="collectionLinearView-menuOpener">
+                {BoolCast(this.layoutDoc.linearViewIsExpanded) ? icon ? icon : <FontAwesomeIcon icon={"minus"} /> : icon ? icon : <FontAwesomeIcon icon={"plus"} />}
+            </div>
+        </label>;
+
+        return <div className={`collectionLinearView-outer ${this.layoutDoc.linearViewSubMenu}`} style={{ backgroundColor: BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : "transparent" }}>
+            <div className="collectionLinearView" ref={this.createDashEventsTarget}
+                onContextMenu={this.myContextMenu} >
+                {!expandable ? (null) : <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close" : "Open"}</div></>} placement="top">
+                    {menuOpener}
+                </Tooltip>}
+                <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
+                    onChange={action(() => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
+
+                <div className="collectionLinearView-content"
+                    style={{
+                        height: this.dimension(),
+                        flexDirection: flexDir,
+                        gap: flexGap
+                    }}>
+                    {this.childLayoutPairs.map((pair, ind) => {
+                        const nested = pair.layout._viewType === CollectionViewType.Linear;
+                        const dref = React.createRef<HTMLDivElement>();
+                        const hidden = pair.layout.hidden === true;
+                        // const scalable = pair.layout.onClick || pair.layout.onDragStart;
+                        return hidden ? (null) : <div className={`collectionLinearView-docBtn`} key={pair.layout[Id]} ref={dref}
+                            style={{
+                                pointerEvents: "all",
+                                width: nested ? undefined : NumCast(pair.layout._width),
+                                height: nested ? undefined : NumCast(pair.layout._height),
+                                marginLeft: !nested ? 2.5 : 0,
+                                marginRight: !nested ? 2.5 : 0,
+                                // width: NumCast(pair.layout._width),
+                                // height: NumCast(pair.layout._height),
+                            }}  >
+                            <DocumentView
+                                Document={pair.layout}
+                                DataDoc={pair.data}
+                                isContentActive={this.props.isContentActive}
+                                isDocumentActive={returnTrue}
+                                addDocument={this.props.addDocument}
+                                moveDocument={this.props.moveDocument}
+                                addDocTab={this.props.addDocTab}
+                                pinToPres={emptyFunction}
+                                rootSelected={this.props.isSelected}
+                                removeDocument={this.props.removeDocument}
+                                ScreenToLocalTransform={this.getTransform(dref)}
+                                PanelWidth={nested ? pair.layout[WidthSym] : this.dimension}
+                                PanelHeight={nested ? pair.layout[HeightSym] : this.dimension}
+                                renderDepth={this.props.renderDepth + 1}
+                                focus={emptyFunction}
+                                styleProvider={this.props.styleProvider}
+                                layerProvider={this.props.layerProvider}
+                                docViewPath={returnEmptyDoclist}
+                                whenChildContentsActiveChanged={emptyFunction}
+                                bringToFront={emptyFunction}
+                                docFilters={this.props.docFilters}
+                                docRangeFilters={this.props.docRangeFilters}
+                                searchFilterDocs={this.props.searchFilterDocs}
+                                ContainingCollectionView={undefined}
+                                ContainingCollectionDoc={undefined} />
+                        </div>;
+                    })}
+                </div>
+                {DocumentLinksButton.StartLink && StrCast(this.layoutDoc.title) === "docked buttons" ? <span className="bottomPopup-background" style={{
+                    pointerEvents: "all"
+                }}
+                    onPointerDown={e => e.stopPropagation()} >
+                    <span className="bottomPopup-text" >
+                        Creating link from: <b>{DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}</b>
+                    </span>
+
+                    <Tooltip title={<><div className="dash-tooltip">{"Toggle description pop-up"} </div></>} placement="top">
+                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
+                            Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
+                        </span>
+                    </Tooltip>
+
+                    <Tooltip title={<><div className="dash-tooltip">Exit linking mode</div></>} placement="top">
+                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}>
+                            Stop
+                        </span>
+                    </Tooltip>
+
+                </span> : null}
+            </div>
+        </div>;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionLinear/index.ts b/src/client/views/collections/collectionLinear/index.ts
new file mode 100644
index 000000000..ff73e14ae
--- /dev/null
+++ b/src/client/views/collections/collectionLinear/index.ts
@@ -0,0 +1 @@
+export * from "./CollectionLinearView";
\ No newline at end of file
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
deleted file mode 100644
index 8fe804466..000000000
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ /dev/null
@@ -1,150 +0,0 @@
-@import "../../global/globalCssVariables";
-@import "../../_nodeModuleOverrides";
-
-.collectionLinearView-outer {
-    overflow: visible;
-    height: 100%;
-    pointer-events: none;
-
-    &.true {
-        padding-left: 5px;
-        padding-right: 5px;
-        border-left: $standard-border;
-        background-color: $medium-blue-alt;
-    }
-
-    >input:not(:checked)~&.true {
-        background-color: transparent;
-    }
-
-    .collectionLinearView {
-        display: flex;
-        height: 100%;
-        align-items: center;
-        gap: 5px;
-
-        .collectionView {
-            overflow: visible !important;
-        }
-
-        >span {
-            background: $dark-gray;
-            color: $white;
-            border-radius: 18px;
-            margin-right: 6px;
-            cursor: pointer;
-        }
-
-        .bottomPopup-background {
-            background: $medium-blue;
-            display: flex;
-            border-radius: 10px;
-            height: 35;
-            transform: translate3d(6px, 0px, 0px);
-            align-content: center;
-            justify-content: center;
-            align-items: center;
-        }
-
-        .bottomPopup-text {
-            color: $white;
-            display: inline;
-            white-space: nowrap;
-            padding-left: 8px;
-            padding-right: 20px;
-            vertical-align: middle;
-            font-size: 12.5px;
-        }
-
-        .bottomPopup-descriptions {
-            cursor: pointer;
-            display: inline;
-            white-space: nowrap;
-            padding-left: 8px;
-            padding-right: 8px;
-            vertical-align: middle;
-            background-color: $light-gray;
-            border-radius: 3px;
-            color: black;
-            margin-right: 5px;
-        }
-
-        .bottomPopup-exit {
-            cursor: pointer;
-            display: inline;
-            white-space: nowrap;
-            margin-right: 10px;
-            padding-left: 8px;
-            padding-right: 8px;
-            vertical-align: middle;
-            background-color: $close-red;
-            border-radius: 3px;
-            color: black;
-        }
-
-        >label {
-            pointer-events: all;
-            cursor: pointer;
-            background-color: $medium-blue;
-            padding: 5;
-            border-radius: 2px;
-            height: 25;
-            min-width: 25;
-            margin: 0;
-            color: $white;
-            display: flex;
-            font-weight: 100;
-            width: fit-content;
-            transition: transform 0.2s;
-            align-items: center;
-            justify-content: center;
-            transition: 0.2s;
-
-            &:hover{
-                filter: brightness(0.85);
-            }
-        }
-
-        >input {
-            display: none;
-        }
-
-        >input:not(:checked)~.collectionLinearView-content {
-            display: none;
-        }
-
-        >input:checked~label {
-            transform: rotate(45deg);
-            transition: transform 0.5s;
-            cursor: pointer;
-        }
-
-        .collectionLinearView-content {
-            display: flex;
-            opacity: 1;
-            position: relative;
-
-            .collectionLinearView-docBtn,
-            .collectionLinearView-docBtn-scalable {
-                position: relative;
-                margin: auto;
-                transform-origin: center 80%;
-            }
-
-            .collectionLinearView-docBtn-scalable:hover {
-                transform: scale(1.15);
-            }
-
-            .collectionLinearView-round-button {
-                width: 18px;
-                height: 18px;
-                border-radius: 18px;
-                font-size: 15px;
-            }
-
-            .collectionLinearView-round-button:hover {
-                transform: scale(1.15);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
deleted file mode 100644
index 8d7809cdb..000000000
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ /dev/null
@@ -1,222 +0,0 @@
-import { Tooltip } from '@material-ui/core';
-import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
-import { Id } from '../../../../fields/FieldSymbols';
-import { makeInterface } from '../../../../fields/Schema';
-import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils';
-import { DragManager } from '../../../util/DragManager';
-import { Transform } from '../../../util/Transform';
-import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
-import { DocumentView } from '../../nodes/DocumentView';
-import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
-import { StyleProp } from '../../StyleProvider';
-import "./CollectionLinearView.scss";
-import { CollectionSubView } from '.././CollectionSubView';
-import { CollectionViewType } from '.././CollectionView';
-import { Colors, Shadows } from '../../global/globalEnums';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-
-
-type LinearDocument = makeInterface<[typeof documentSchema,]>;
-const LinearDocument = makeInterface(documentSchema);
-
-@observer
-export class CollectionLinearView extends CollectionSubView(LinearDocument) {
-    @observable public addMenuToggle = React.createRef<HTMLInputElement>();
-    @observable private _selectedIndex = -1;
-    private _dropDisposer?: DragManager.DragDropDisposer;
-    private _widthDisposer?: IReactionDisposer;
-    private _selectedDisposer?: IReactionDisposer;
-
-    componentWillUnmount() {
-        this._dropDisposer?.();
-        this._widthDisposer?.();
-        this._selectedDisposer?.();
-        this.childLayoutPairs.map((pair, ind) => ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
-    }
-
-    componentDidMount() {
-        this._widthDisposer = reaction(() => 5 + (this.layoutDoc.linearViewIsExpanded ? this.childDocs.length * (this.rootDoc[HeightSym]()) : 10),
-            width => this.childDocs.length && (this.layoutDoc._width = width),
-            { fireImmediately: true }
-        );
-
-        this._selectedDisposer = reaction(
-            () => NumCast(this.layoutDoc.selectedIndex),
-            (i) => runInAction(() => {
-                this._selectedIndex = i;
-                let selected: any = undefined;
-                this.childLayoutPairs.map(async (pair, ind) => {
-                    const isSelected = this._selectedIndex === ind;
-                    if (isSelected) {
-                        selected = pair;
-                    }
-                    else {
-                        ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log);
-                    }
-                });
-                if (selected && selected.layout) {
-                    ScriptCast(selected.layout.proto?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log);
-                }
-            }),
-            { fireImmediately: true }
-        );
-    }
-    protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
-        this._dropDisposer && this._dropDisposer();
-        if (ele) {
-            this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc);
-        }
-    }
-
-    dimension = () => NumCast(this.rootDoc._height); // 2 * the padding
-    getTransform = (ele: React.RefObject<HTMLDivElement>) => () => {
-        if (!ele.current) return Transform.Identity();
-        const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current);
-        return new Transform(-translateX, -translateY, 1);
-    }
-
-    @action
-    exitLongLinks = () => {
-        if (DocumentLinksButton.StartLink) {
-            if (DocumentLinksButton.StartLink.Document) {
-                action((e: React.PointerEvent<HTMLDivElement>) => {
-                    Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc);
-                });
-            }
-        }
-        DocumentLinksButton.StartLink = undefined;
-        DocumentLinksButton.StartLinkView = undefined;
-    }
-
-    @action
-    changeDescriptionSetting = () => {
-        if (LinkDescriptionPopup.showDescriptions) {
-            if (LinkDescriptionPopup.showDescriptions === "ON") {
-                LinkDescriptionPopup.showDescriptions = "OFF";
-                LinkDescriptionPopup.descriptionPopup = false;
-            } else {
-                LinkDescriptionPopup.showDescriptions = "ON";
-            }
-        } else {
-            LinkDescriptionPopup.showDescriptions = "OFF";
-            LinkDescriptionPopup.descriptionPopup = false;
-        }
-    }
-
-    myContextMenu = (e: React.MouseEvent) => {
-        console.log("STOPPING");
-        e.stopPropagation();
-        e.preventDefault();
-    }
-
-    render() {
-        const guid = Utils.GenerateGuid(); // Generate a unique ID to use as the label
-        const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content
-        const flexGap: number = NumCast(this.Document.flexGap); // Specify the gap between linear view content
-        const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable); // Specify whether it is expandable or not
-        const floating: boolean = BoolCast(this.props.Document.linearViewFloating); // Specify whether it is expandable or not
-
-        const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
-        const icon: string = StrCast(this.props.Document.icon); // Menu opener toggle
-        const menuOpener = <label htmlFor={`${guid}`}
-            style={{
-                boxShadow: floating ? Shadows.STANDARD_SHADOW : undefined,
-                color: BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : Colors.BLACK,
-                backgroundColor: backgroundColor === color ? "black" : BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : Colors.LIGHT_GRAY
-            }}
-            onPointerDown={e => e.stopPropagation()} >
-            <div className="collectionLinearView-menuOpener">
-                {BoolCast(this.layoutDoc.linearViewIsExpanded) ? icon ? icon : <FontAwesomeIcon icon={"minus"} /> : icon ? icon : <FontAwesomeIcon icon={"plus"} />}
-            </div>
-        </label>;
-
-        return <div className={`collectionLinearView-outer ${this.layoutDoc.linearViewSubMenu}`} style={{ backgroundColor: BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : "transparent" }}>
-            <div className="collectionLinearView" ref={this.createDashEventsTarget}
-                onContextMenu={this.myContextMenu} >
-                {!expandable ? (null) : <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close" : "Open"}</div></>} placement="top">
-                    {menuOpener}
-                </Tooltip>}
-                <input id={`${guid}`} type="checkbox" checked={BoolCast(this.props.Document.linearViewIsExpanded)} ref={this.addMenuToggle}
-                    onChange={action(() => this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
-
-                <div className="collectionLinearView-content"
-                    style={{
-                        height: this.dimension(),
-                        flexDirection: flexDir,
-                        gap: flexGap
-                    }}>
-                    {this.childLayoutPairs.map((pair, ind) => {
-                        const nested = pair.layout._viewType === CollectionViewType.Linear;
-                        const dref = React.createRef<HTMLDivElement>();
-                        const hidden = pair.layout.hidden === true;
-                        // const scalable = pair.layout.onClick || pair.layout.onDragStart;
-                        return hidden ? (null) : <div className={`collectionLinearView-docBtn`} key={pair.layout[Id]} ref={dref}
-                            style={{
-                                pointerEvents: "all",
-                                width: nested ? undefined : NumCast(pair.layout._width),
-                                height: nested ? undefined : NumCast(pair.layout._height),
-                                marginLeft: !nested ? 2.5 : 0,
-                                marginRight: !nested ? 2.5 : 0,
-                                // width: NumCast(pair.layout._width),
-                                // height: NumCast(pair.layout._height),
-                            }}  >
-                            <DocumentView
-                                Document={pair.layout}
-                                DataDoc={pair.data}
-                                isContentActive={this.props.isContentActive}
-                                isDocumentActive={returnTrue}
-                                addDocument={this.props.addDocument}
-                                moveDocument={this.props.moveDocument}
-                                addDocTab={this.props.addDocTab}
-                                pinToPres={emptyFunction}
-                                rootSelected={this.props.isSelected}
-                                removeDocument={this.props.removeDocument}
-                                ScreenToLocalTransform={this.getTransform(dref)}
-                                PanelWidth={nested ? pair.layout[WidthSym] : this.dimension}
-                                PanelHeight={nested ? pair.layout[HeightSym] : this.dimension}
-                                renderDepth={this.props.renderDepth + 1}
-                                focus={emptyFunction}
-                                styleProvider={this.props.styleProvider}
-                                layerProvider={this.props.layerProvider}
-                                docViewPath={returnEmptyDoclist}
-                                whenChildContentsActiveChanged={emptyFunction}
-                                bringToFront={emptyFunction}
-                                docFilters={this.props.docFilters}
-                                docRangeFilters={this.props.docRangeFilters}
-                                searchFilterDocs={this.props.searchFilterDocs}
-                                ContainingCollectionView={undefined}
-                                ContainingCollectionDoc={undefined} />
-                        </div>;
-                    })}
-                </div>
-                {DocumentLinksButton.StartLink && StrCast(this.layoutDoc.title) === "docked buttons" ? <span className="bottomPopup-background" style={{
-                    pointerEvents: "all"
-                }}
-                    onPointerDown={e => e.stopPropagation()} >
-                    <span className="bottomPopup-text" >
-                        Creating link from: <b>{DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}</b>
-                    </span>
-
-                    <Tooltip title={<><div className="dash-tooltip">{"Toggle description pop-up"} </div></>} placement="top">
-                        <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
-                            Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
-                        </span>
-                    </Tooltip>
-
-                    <Tooltip title={<><div className="dash-tooltip">Exit linking mode</div></>} placement="top">
-                        <span className="bottomPopup-exit" onClick={this.exitLongLinks}>
-                            Stop
-                        </span>
-                    </Tooltip>
-
-                </span> : null}
-            </div>
-        </div>;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionLinearView/index.ts b/src/client/views/collections/collectionLinearView/index.ts
deleted file mode 100644
index ff73e14ae..000000000
--- a/src/client/views/collections/collectionLinearView/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./CollectionLinearView";
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 3ae79d3742030a255855d0c9c4ba8345f1cc73dd Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 9 Sep 2021 17:10:36 -0400
Subject: fixed infinite loop for context menus when right-clicking on them.

---
 src/client/util/CurrentUserUtils.ts                |   6 +-
 src/client/views/collections/CollectionMenu.tsx    |  10 +-
 .../collectionLinear/CollectionLinearView.tsx      | 101 +++++++++++----------
 3 files changed, 63 insertions(+), 54 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 816503b37..8435825c9 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1050,7 +1050,7 @@ export class CurrentUserUtils {
             }, // Only when a document is selected
             {
                 title: "Header Color", toolTip: "Header Color", btnType: ButtonType.ColorButton, ignoreClick: true, icon: "heading",
-                script: "setHeaderColor", hidden: 'selectedDocumentType()'
+                script: "setHeaderColor", hidden: 'selectedDocumentType()',
             }, // Only when a document is selected
             { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()', checkResult: 'toggleOverlay(true)', hidden: 'selectedDocumentType(undefined, "freeform", true)' }, // Only when floating document is selected in freeform
             // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy", hidden: 'selectedDocumentType()' }, // Only when a document is selected 
@@ -1137,9 +1137,9 @@ export class CurrentUserUtils {
                         icon,
                         toolTip,
                         script,
-                        btnType: btnType,
+                        btnType,
                         btnList: new List<string>(list),
-                        ignoreClick: ignoreClick,
+                        ignoreClick,
                         _stayInCollection: true,
                         _hideContextMenu: true,
                         _lockedPosition: true,
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 86bf9ad41..ce5846502 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome";
 import { Tooltip } from "@material-ui/core";
-import { action, computed, Lambda, observable, reaction, runInAction } from "mobx";
+import { action, computed, Lambda, observable, reaction, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import { ColorState } from "react-color";
 import { Doc, DocListCast, Opt } from "../../../fields/Doc";
@@ -93,7 +93,11 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
         return new Transform(-translateX, -translateY, 1 / scale);
     }
 
+    panelWidth100 = () => 100;
+    panelHeight35 = () => 35;
+
     @computed get contMenuButtons() {
+        trace();
         const selDoc = Doc.UserDoc().contextMenuBtns;
         return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: "35px" }} >
             <CollectionLinearView
@@ -118,8 +122,8 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
                 pinToPres={emptyFunction}
                 removeDocument={returnFalse}
                 ScreenToLocalTransform={this.buttonBarXf}
-                PanelWidth={() => 100}
-                PanelHeight={() => 35}
+                PanelWidth={this.panelWidth100}
+                PanelHeight={this.panelHeight35}
                 renderDepth={0}
                 focus={emptyFunction}
                 whenChildContentsActiveChanged={emptyFunction}
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index e78ca2a32..fae92e076 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -1,8 +1,8 @@
 import { Tooltip } from '@material-ui/core';
-import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, HeightSym, WidthSym } from '../../../../fields/Doc';
+import { Doc, HeightSym, WidthSym, Opt } from '../../../../fields/Doc';
 import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
 import { makeInterface } from '../../../../fields/Schema';
@@ -74,9 +74,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
     }
 
     dimension = () => NumCast(this.rootDoc._height); // 2 * the padding
-    getTransform = (ele: React.RefObject<HTMLDivElement>) => () => {
-        if (!ele.current) return Transform.Identity();
-        const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current);
+    getTransform = (ele: Opt<HTMLDivElement>) => {
+        if (!ele) return Transform.Identity();
+        const { scale, translateX, translateY } = Utils.GetScreenTransform(ele);
         return new Transform(-translateX, -translateY, 1);
     }
 
@@ -114,6 +114,53 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
         e.preventDefault();
     }
 
+
+    getDisplayDoc(doc: Doc) {
+        const nested = doc._viewType === CollectionViewType.Linear;
+        const hidden = doc.hidden === true;;
+
+        let dref: Opt<HTMLDivElement>;
+        const docXf = () => this.getTransform(dref);
+        // const scalable = pair.layout.onClick || pair.layout.onDragStart;
+        return hidden ? (null) : <div className={`collectionLinearView-docBtn`} key={doc[Id]} ref={r => dref = r || undefined}
+            style={{
+                pointerEvents: "all",
+                width: nested ? undefined : NumCast(doc._width),
+                height: nested ? undefined : NumCast(doc._height),
+                marginLeft: !nested ? 2.5 : 0,
+                marginRight: !nested ? 2.5 : 0,
+                // width: NumCast(pair.layout._width),
+                // height: NumCast(pair.layout._height),
+            }}  >
+            <DocumentView
+                Document={doc}
+                isContentActive={this.props.isContentActive}
+                isDocumentActive={returnTrue}
+                addDocument={this.props.addDocument}
+                moveDocument={this.props.moveDocument}
+                addDocTab={this.props.addDocTab}
+                pinToPres={emptyFunction}
+                rootSelected={this.props.isSelected}
+                removeDocument={this.props.removeDocument}
+                // ScreenToLocalTransform={docXf} // bcz: Ugh -- this is what we want, but it breaks things when right-clicking on linear view item since docXf is not a constant value across invalidations
+                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                PanelWidth={nested ? doc[WidthSym] : this.dimension}
+                PanelHeight={nested ? doc[HeightSym] : this.dimension}
+                renderDepth={this.props.renderDepth + 1}
+                focus={emptyFunction}
+                styleProvider={this.props.styleProvider}
+                layerProvider={this.props.layerProvider}
+                docViewPath={returnEmptyDoclist}
+                whenChildContentsActiveChanged={emptyFunction}
+                bringToFront={emptyFunction}
+                docFilters={this.props.docFilters}
+                docRangeFilters={this.props.docRangeFilters}
+                searchFilterDocs={this.props.searchFilterDocs}
+                ContainingCollectionView={undefined}
+                ContainingCollectionDoc={undefined} />
+        </div>;
+    }
+
     render() {
         const guid = Utils.GenerateGuid(); // Generate a unique ID to use as the label
         const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content
@@ -151,49 +198,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                         flexDirection: flexDir,
                         gap: flexGap
                     }}>
-                    {this.childLayoutPairs.map((pair, ind) => {
-                        const nested = pair.layout._viewType === CollectionViewType.Linear;
-                        const dref = React.createRef<HTMLDivElement>();
-                        const hidden = pair.layout.hidden === true;
-                        // const scalable = pair.layout.onClick || pair.layout.onDragStart;
-                        return hidden ? (null) : <div className={`collectionLinearView-docBtn`} key={pair.layout[Id]} ref={dref}
-                            style={{
-                                pointerEvents: "all",
-                                width: nested ? undefined : NumCast(pair.layout._width),
-                                height: nested ? undefined : NumCast(pair.layout._height),
-                                marginLeft: !nested ? 2.5 : 0,
-                                marginRight: !nested ? 2.5 : 0,
-                                // width: NumCast(pair.layout._width),
-                                // height: NumCast(pair.layout._height),
-                            }}  >
-                            <DocumentView
-                                Document={pair.layout}
-                                DataDoc={pair.data}
-                                isContentActive={this.props.isContentActive}
-                                isDocumentActive={returnTrue}
-                                addDocument={this.props.addDocument}
-                                moveDocument={this.props.moveDocument}
-                                addDocTab={this.props.addDocTab}
-                                pinToPres={emptyFunction}
-                                rootSelected={this.props.isSelected}
-                                removeDocument={this.props.removeDocument}
-                                ScreenToLocalTransform={this.getTransform(dref)}
-                                PanelWidth={nested ? pair.layout[WidthSym] : this.dimension}
-                                PanelHeight={nested ? pair.layout[HeightSym] : this.dimension}
-                                renderDepth={this.props.renderDepth + 1}
-                                focus={emptyFunction}
-                                styleProvider={this.props.styleProvider}
-                                layerProvider={this.props.layerProvider}
-                                docViewPath={returnEmptyDoclist}
-                                whenChildContentsActiveChanged={emptyFunction}
-                                bringToFront={emptyFunction}
-                                docFilters={this.props.docFilters}
-                                docRangeFilters={this.props.docRangeFilters}
-                                searchFilterDocs={this.props.searchFilterDocs}
-                                ContainingCollectionView={undefined}
-                                ContainingCollectionDoc={undefined} />
-                        </div>;
-                    })}
+                    {this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
                 </div>
                 {DocumentLinksButton.StartLink && StrCast(this.layoutDoc.title) === "docked buttons" ? <span className="bottomPopup-background" style={{
                     pointerEvents: "all"
-- 
cgit v1.2.3-70-g09d2


From 9d177851ecaaea1a89ac9b7de1cec16368603eaa Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 9 Sep 2021 22:49:13 -0400
Subject: added SelectionManager.Docs() to avoid having to dereference props to
 get at the seelcted Doc.  this was causing a cycle in menu items when
 selected.  fixed sizing of filterBox.  enabled showing titles for VID,COL,and
 IMG in addition to RTF.

---
 src/client/util/CurrentUserUtils.ts                |  2 +-
 src/client/util/HypothesisUtils.ts                 |  2 +-
 src/client/util/SelectionManager.ts                | 12 ++--
 src/client/views/GlobalKeyHandler.ts               |  4 +-
 src/client/views/PropertiesView.tsx                |  2 +-
 src/client/views/StyleProvider.tsx                 |  2 +-
 src/client/views/collections/CollectionMenu.tsx    | 21 +++----
 src/client/views/collections/CollectionSubView.tsx |  8 +--
 .../collectionLinear/CollectionLinearView.tsx      | 19 +++---
 src/client/views/nodes/DocumentView.tsx            |  5 +-
 src/client/views/nodes/FilterBox.tsx               | 11 ++--
 src/client/views/nodes/button/FontIconBox.tsx      | 68 ++++++++++------------
 .../views/nodes/formattedText/RichTextMenu.tsx     | 20 +++----
 13 files changed, 81 insertions(+), 95 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 8435825c9..60bb375c8 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1616,7 +1616,7 @@ Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) {
     return [];
 });
 Scripting.addGlobal(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkParent?: boolean) {
-    let selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+    let selected = SelectionManager.Docs().length ? SelectionManager.Docs()[0] : undefined;
     if (selected && checkParent) {
         const parentDoc: Doc = Cast(selected.context, Doc, null);
         selected = parentDoc;
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 635673025..e910a9118 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -29,7 +29,7 @@ export namespace Hypothesis {
      * Search for a WebDocument whose url field matches the given uri, return undefined if not found
      */
     export const findWebDoc = async (uri: string) => {
-        const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document;
+        const currentDoc = SelectionManager.Docs().lastElement();
         if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the currently selected doc is the annotation's source, only use Search otherwise
 
         const results: Doc[] = [];
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0cfaebbf2..bac13373c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -11,7 +11,7 @@ export namespace SelectionManager {
     class Manager {
 
         @observable IsDragging: boolean = false;
-        SelectedViews: ObservableMap<DocumentView, boolean> = new ObservableMap();
+        SelectedViews: ObservableMap<DocumentView, Doc> = new ObservableMap();
         @observable SelectedSchemaDocument: Doc | undefined;
         @observable SelectedSchemaCollection: CollectionSchemaView | undefined;
 
@@ -28,19 +28,18 @@ export namespace SelectionManager {
                     this.DeselectAll();
                 }
 
-                manager.SelectedViews.set(docView, true);
+                manager.SelectedViews.set(docView, docView.rootDoc);
                 docView.props.whenChildContentsActiveChanged(true);
             } else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) {
                 Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false));
                 manager.SelectedSchemaDocument = undefined;
                 manager.SelectedSchemaCollection = undefined;
                 manager.SelectedViews.clear();
-                manager.SelectedViews.set(docView, true);
+                manager.SelectedViews.set(docView, docView.rootDoc);
             }
         }
         @action
         DeselectView(docView: DocumentView): void {
-
             if (manager.SelectedViews.get(docView)) {
                 manager.SelectedViews.delete(docView);
                 docView.props.whenChildContentsActiveChanged(false);
@@ -92,7 +91,7 @@ export namespace SelectionManager {
     }
 
     export function Views(): Array<DocumentView> {
-        return Array.from(manager.SelectedViews.keys()).filter(dv => dv.props.Document._viewType !== CollectionViewType.Docking);
+        return Array.from(manager.SelectedViews.keys()).filter(dv => manager.SelectedViews.get(dv)?._viewType !== CollectionViewType.Docking);
     }
     export function SelectedSchemaDoc(): Doc | undefined {
         return manager.SelectedSchemaDocument;
@@ -100,4 +99,7 @@ export namespace SelectionManager {
     export function SelectedSchemaCollection(): CollectionSchemaView | undefined {
         return manager.SelectedSchemaCollection;
     }
+    export function Docs(): Doc[] {
+        return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking);
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 0127d3080..f66c9c788 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -229,8 +229,8 @@ export class KeyManager {
                 }
                 break;
             case "o":
-                const target = SelectionManager.Views()[0];
-                target && CollectionDockingView.OpenFullScreen(target.props.Document);
+                const target = SelectionManager.Docs().lastElement();
+                target && CollectionDockingView.OpenFullScreen(target);
                 break;
             case "r":
                 preventDefault = false;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 09e12443b..ab9022a84 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -366,7 +366,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         return <Tooltip title={<div className="dash-tooltip">{"Show more permissions"}</div>}>
             <div className="expansion-button" onPointerDown={() => {
                 if (this.selectedDocumentView || this.selectedDoc) {
-                    SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDocumentView ? this.selectedDocumentView : undefined, this.selectedDoc);
+                    SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc);
                 }
             }}>
                 <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" />
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 3413179ed..3c88a4830 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -96,7 +96,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.ShowTitle: return (doc && !doc.presentationTargetDoc &&
             StrCast(doc._showTitle,
                 props?.showTitle?.() ||
-                (!Doc.IsSystem(doc) && doc.type === DocumentType.RTF ?
+                (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
                     (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) :
                         "author;creationDate") : "")) || "");
         case StyleProp.Color:
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index ce5846502..aefa1ec3d 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -62,7 +62,7 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     componentDidMount() {
         reaction(() => SelectionManager.Views().length && SelectionManager.Views()[0],
-            (doc) => doc && this.SetSelection(doc));
+            view => view && this.SetSelection(view));
     }
 
     @action
@@ -441,10 +441,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         </div>);
     }
 
-    @computed get selectedDocumentView() {
-        return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-    }
-    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get selectedDocumentView() { return SelectionManager.Views().lastElement(); }
+    @computed get selectedDoc() { return SelectionManager.Docs().lastElement(); }
     @computed get notACollection() {
         if (this.selectedDoc) {
             const layoutField = Doc.LayoutField(this.selectedDoc);
@@ -552,8 +550,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     @undoBatch
     onAliasButtonMoved = (e: PointerEvent) => {
         const contentDiv = this.selectedDocumentView?.ContentDiv;
-        if (contentDiv) {
-            const dragData = new DragManager.DocumentDragData([this.selectedDocumentView!.props.Document]);
+        if (contentDiv && this.selectedDoc) {
+            const dragData = new DragManager.DocumentDragData([this.selectedDoc]);
             const offset = [e.clientX - contentDiv.getBoundingClientRect().x, e.clientY - contentDiv.getBoundingClientRect().y];
             dragData.defaultDropAction = "alias";
             dragData.canEmbed = true;
@@ -648,11 +646,9 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
         return this.document[this.props.docView.LayoutFieldKey + (this.props.isOverlay ? "-annotations" : "")];
     }
     @computed get childDocs() { return DocListCast(this.dataField); }
-    @computed get selectedDocumentView() { return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; }
-    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
-    @computed get isText() {
-        return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any) ? true : false;
-    }
+    @computed get selectedDocumentView() { return SelectionManager.Views().lastElement(); }
+    @computed get selectedDoc() { return SelectionManager.Docs().lastElement(); }
+    @computed get isText() { return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any) ? true : false; }
 
     @undoBatch
     @action
@@ -826,7 +822,6 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
 
             </div>;
     }
-    @observable viewType = this.selectedDoc?._viewType;
 
     render() {
         return !this.props.docView.layoutDoc ? (null) :
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b70df93da..06d20f015 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -321,12 +321,8 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                                 }
                             });
                         } else {
-                            let srcUrl: string | undefined;
-                            let srcWeb: Doc | undefined;
-                            if (SelectionManager.Views().length) {
-                                srcWeb = SelectionManager.Views()[0].props.Document;
-                                srcUrl = (srcWeb.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0];
-                            }
+                            const srcWeb = SelectionManager.Docs().lastElement();
+                            const srcUrl = (srcWeb?.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0];
                             const reg = new RegExp(Utils.prepend(""), "g");
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
                             const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 });
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index fae92e076..7fe95fef0 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -1,24 +1,24 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { action, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx';
+import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, HeightSym, WidthSym, Opt } from '../../../../fields/Doc';
+import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
 import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
 import { makeInterface } from '../../../../fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, Utils } from '../../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils';
 import { DragManager } from '../../../util/DragManager';
 import { Transform } from '../../../util/Transform';
+import { Colors, Shadows } from '../../global/globalEnums';
 import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
 import { DocumentView } from '../../nodes/DocumentView';
 import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
 import { StyleProp } from '../../StyleProvider';
-import "./CollectionLinearView.scss";
 import { CollectionSubView } from '../CollectionSubView';
 import { CollectionViewType } from '../CollectionView';
-import { Colors, Shadows } from '../../global/globalEnums';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import "./CollectionLinearView.scss";
 
 
 type LinearDocument = makeInterface<[typeof documentSchema,]>;
@@ -115,9 +115,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
     }
 
 
-    getDisplayDoc(doc: Doc) {
+    getDisplayDoc = (doc: Doc) => {
         const nested = doc._viewType === CollectionViewType.Linear;
-        const hidden = doc.hidden === true;;
+        const hidden = doc.hidden === true;
 
         let dref: Opt<HTMLDivElement>;
         const docXf = () => this.getTransform(dref);
@@ -142,8 +142,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                 pinToPres={emptyFunction}
                 rootSelected={this.props.isSelected}
                 removeDocument={this.props.removeDocument}
-                // ScreenToLocalTransform={docXf} // bcz: Ugh -- this is what we want, but it breaks things when right-clicking on linear view item since docXf is not a constant value across invalidations
-                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                ScreenToLocalTransform={docXf}
                 PanelWidth={nested ? doc[WidthSym] : this.dimension}
                 PanelHeight={nested ? doc[HeightSym] : this.dimension}
                 renderDepth={this.props.renderDepth + 1}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6f97cdbd8..8b19fb204 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -649,7 +649,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         if (e && this.rootDoc._hideContextMenu && Doc.UserDoc().noviceMode) {
             e.preventDefault();
             e.stopPropagation();
-            !this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
+            //!this.props.isSelected(true) && SelectionManager.SelectView(this.props.DocumentView(), false);
         }
         // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
         if (e) {
@@ -952,11 +952,12 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     hideOnLeave={true}
                     styleProvider={this.captionStyleProvider}
                     dontRegisterView={true}
+                    isContentActive={this.isContentActive}
                     onClick={this.onClickFunc}
                 />
             </div>;
         const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc);
-        const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, this.rootDoc.type === DocumentType.RTF ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
+        const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
         const titleView = !showTitle ? (null) :
             <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
                 position: this.headerMargin ? "relative" : "absolute",
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 7ad03e055..e9f19bf9e 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -9,7 +9,7 @@ import { List } from "../../../fields/List";
 import { RichTextField } from "../../../fields/RichTextField";
 import { listSpec, makeInterface } from "../../../fields/Schema";
 import { ComputedField, ScriptField } from "../../../fields/ScriptField";
-import { Cast, StrCast } from "../../../fields/Types";
+import { Cast, StrCast, NumCast } from "../../../fields/Types";
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
@@ -79,7 +79,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
     * @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection
     */
     @computed static get targetDoc() {
-        return SelectionManager.Views().length ? SelectionManager.Views()[0].Document : CurrentUserUtils.ActiveDashboard;
+        return SelectionManager.Docs().length ? SelectionManager.Docs()[0] : CurrentUserUtils.ActiveDashboard;
     }
     @computed static get targetDocChildKey() {
         if (SelectionManager.Views().length) {
@@ -88,10 +88,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
         return "data";
     }
     @computed static get targetDocChildren() {
-        if (SelectionManager.Views().length) {
-            return DocListCast(FilterBox.targetDoc[FilterBox.targetDocChildKey]);
-        }
-        return DocListCast(CurrentUserUtils.ActiveDashboard.data);
+        return DocListCast(FilterBox.targetDoc?.[FilterBox.targetDocChildKey] || CurrentUserUtils.ActiveDashboard.data);
     }
 
     @observable _loaded = false;
@@ -347,7 +344,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
         );
     }
     setTreeHeight = (hgt: number) => {
-        this.layoutDoc._height = hgt + 140; // 50?  need to add all the border sizes together.
+        this.layoutDoc._height = NumCast(this.layoutDoc._autoHeightMargins) + 150; // need to add all the border sizes together.
     }
 
     /**
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 4475cf347..df7c54f67 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -248,14 +248,15 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         let noneSelected: boolean = false;
 
         if (script === 'setView') {
-            const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-            if (selected && StrCast(selected.Document.type) === DocumentType.COL) {
-                text = StrCast(selected.Document._viewType);
-            } else if (selected) {
-                dropdown = false;
-                text = StrCast(selected.Document.type);
-                if (text === DocumentType.RTF) text = "Text";
-                icon = Doc.toIcon(selected.Document);
+            const selected = SelectionManager.Docs().lastElement();
+            if (selected) {
+                if (StrCast(selected.type) === DocumentType.COL) {
+                    text = StrCast(selected._viewType);
+                } else {
+                    dropdown = false;
+                    text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type);
+                    icon = Doc.toIcon(selected);
+                }
             } else {
                 dropdown = false;
                 icon = "globe-asia";
@@ -263,13 +264,8 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             }
             noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
         } else if (script === 'setFont') {
-            const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-            if (selected && StrCast(selected.Document.type) === DocumentType.RTF) {
-                text = StrCast(selected.Document._fontFamily);
-            } else {
-                const fontFamily = StrCast(Doc.UserDoc()._fontFamily);
-                text = fontFamily;
-            }
+            const selected = SelectionManager.Docs().lastElement();
+            text = StrCast((selected?.type === DocumentType.RTF ? selected : Doc.UserDoc())._fontFamily);
             noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
                 "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
         }
@@ -584,13 +580,13 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setView(view: string) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-    selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
+    const selected = SelectionManager.Docs().lastElement();
+    selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
 });
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+    const selected = SelectionManager.Docs().lastElement();
     if (checkResult) {
         if (selected) {
             console.log("[Background] (selected): " + StrCast(selected._backgroundColor));
@@ -635,7 +631,7 @@ Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) {
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setFont(font: string, checkResult?: boolean) {
-    SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font);
+    SelectionManager.Docs().map(doc => doc._fontFamily = font);
     const editorView = RichTextMenu.Instance.TextView?.EditorView;
     editorView?.state && RichTextMenu.Instance.setFontFamily(font, editorView);
     Doc.UserDoc()._fontFamily = font;
@@ -665,7 +661,7 @@ Scripting.addGlobal(function setAlignment(align: "left" | "right" | "center", ch
         if (active === align) return Colors.MEDIUM_BLUE;
         else return "transparent";
     }
-    SelectionManager.Views().map(dv => dv.props.Document.textAlign = align);
+    SelectionManager.Docs().map(doc => doc.textAlign = align);
     switch (align) {
         case "left":
             editorView?.state && RichTextMenu.Instance.alignLeft(editorView, editorView.dispatch);
@@ -703,13 +699,13 @@ Scripting.addGlobal(function setBulletList(mapStyle: "bullet" | "decimal", check
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    const selected = SelectionManager.Docs().lastElement();
     const editorView = RichTextMenu.Instance.TextView?.EditorView;
 
     if (checkResult) {
         if (selected) {
-            console.log("[Font color] (selected): " + StrCast(selected.rootDoc._fontColor));
-            return selected.rootDoc._fontColor;
+            console.log("[Font color] (selected): " + StrCast(selected._fontColor));
+            return selected._fontColor;
         } else {
             console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor));
             return Doc.UserDoc()._fontColor;
@@ -717,7 +713,7 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean)
     }
 
     if (selected) {
-        selected.rootDoc._fontColor = color;
+        selected._fontColor = color;
         if (color) {
             editorView?.state && RichTextMenu.Instance.setColor(color, editorView, editorView?.dispatch);
         }
@@ -727,18 +723,18 @@ Scripting.addGlobal(function setFontColor(color?: string, checkResult?: boolean)
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setFontHighlight(color?: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    const selected = SelectionManager.Docs().lastElement();
     const editorView = RichTextMenu.Instance.TextView?.EditorView;
 
     if (checkResult) {
         if (selected) {
-            return selected.Document._fontHighlight;
+            return selected._fontHighlight;
         } else {
             return Doc.UserDoc()._fontHighlight;
         }
     }
     if (selected) {
-        selected.rootDoc._fontColor = color;
+        selected._fontColor = color;
         if (color) {
             editorView?.state && RichTextMenu.Instance.setHighlight(color, editorView, editorView?.dispatch);
         }
@@ -769,7 +765,7 @@ Scripting.addGlobal(function toggleBold(checkResult?: boolean) {
         console.log("editorView");
         editorView?.state && RichTextMenu.Instance.toggleBold(editorView, true);
     }
-    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.bold = !dv.props.Document.bold);
+    SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.bold = !doc.bold);
     Doc.UserDoc().bold = !Doc.UserDoc().bold;
     return Doc.UserDoc().bold;
 });
@@ -784,7 +780,7 @@ Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) {
         console.log("editorView");
         editorView?.state && RichTextMenu.Instance.toggleUnderline(editorView, true);
     }
-    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.underline = !dv.props.Document.underline);
+    SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.underline = !doc.underline);
     Doc.UserDoc().underline = !Doc.UserDoc().underline;
     return Doc.UserDoc().underline;
 });
@@ -799,7 +795,7 @@ Scripting.addGlobal(function toggleItalic(checkResult?: boolean) {
         console.log("editorView");
         editorView?.state && RichTextMenu.Instance.toggleItalic(editorView, true);
     }
-    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.RTF).map(dv => dv.props.Document.italic = !dv.props.Document.italic);
+    SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.RTF).map(doc => doc.italic = !doc.italic);
     Doc.UserDoc().italic = !Doc.UserDoc().italic;
     return Doc.UserDoc().italic;
 });
@@ -841,7 +837,7 @@ Scripting.addGlobal(function setActiveInkTool(tool: string, checkResult?: boolea
 
 Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean) {
     if (checkResult) {
-        const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+        const selected = SelectionManager.Docs().lastElement();
         if (selected && selected.type === DocumentType.INK) {
             return Number(selected.strokeWidth);
         } else {
@@ -850,13 +846,13 @@ Scripting.addGlobal(function setStrokeWidth(width: number, checkResult?: boolean
         }
     }
     Doc.UserDoc().activeInkWidth = width;
-    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(width));
+    SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.strokeWidth = Number(width));
 });
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolean) {
     if (checkResult) {
-        const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+        const selected = SelectionManager.Docs().lastElement();
         if (selected && selected.type === DocumentType.INK) {
             return selected.color;
         } else {
@@ -865,7 +861,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea
         }
     }
     SetActiveInkColor(StrCast(color));
-    SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.color = String(color));
+    SelectionManager.Docs().filter(doc => StrCast(doc.type) === DocumentType.INK).map(doc => doc.color = String(color));
 });
 
 
@@ -873,7 +869,7 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea
  *      webSetURL
  **/
 Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+    const selected = SelectionManager.Docs().lastElement();
     console.log("URL: ", url);
     if (checkResult && selected && selected.type === DocumentType.WEB) {
         return Cast(selected.data, WebField, null).url;
@@ -888,7 +884,7 @@ Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) {
  *      toggleSchemaPreview
  **/
 Scripting.addGlobal(function toggleSchemaPreview(checkResult?: boolean) {
-    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0].rootDoc : undefined;
+    const selected = SelectionManager.Docs().lastElement();
     console.log(selected && selected.title);
     if (checkResult && selected) {
         const result: boolean = NumCast(selected.schemaPreviewWidth) > 0;
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 3d9d9543d..3919fbf94 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -279,33 +279,33 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
         });
     }
 
-    toggleBold = (view: EditorView, forceBool?:boolean) => {
-        const mark = view.state.schema.mark(view.state.schema.marks.strong, {strong: forceBool});
+    toggleBold = (view: EditorView, forceBool?: boolean) => {
+        const mark = view.state.schema.mark(view.state.schema.marks.strong, { strong: forceBool });
         this.setMark(mark, view.state, view.dispatch, false);
         view.focus();
     }
 
-    toggleUnderline = (view: EditorView, forceBool?:boolean) => {
-        const mark = view.state.schema.mark(view.state.schema.marks.underline, {underline: forceBool});
+    toggleUnderline = (view: EditorView, forceBool?: boolean) => {
+        const mark = view.state.schema.mark(view.state.schema.marks.underline, { underline: forceBool });
         this.setMark(mark, view.state, view.dispatch, false);
         view.focus();
     }
 
-    toggleItalic = (view: EditorView, forceBool?:boolean) => {
-        const mark = view.state.schema.mark(view.state.schema.marks.em, {em: forceBool});
+    toggleItalic = (view: EditorView, forceBool?: boolean) => {
+        const mark = view.state.schema.mark(view.state.schema.marks.em, { em: forceBool });
         this.setMark(mark, view.state, view.dispatch, false);
         view.focus();
     }
 
 
-    setFontSize = (size:number, view: EditorView) => {
+    setFontSize = (size: number, view: EditorView) => {
         const fmark = view.state.schema.marks.pFontSize.create({ fontSize: size });
         this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true);
         view.focus();
         this.updateMenu(view, undefined, this.props);
     }
 
-    setFontFamily = (family:string, view: EditorView) => {
+    setFontFamily = (family: string, view: EditorView) => {
         const fmark = view.state.schema.marks.pFontFamily.create({ family: family });
         this.setMark(fmark, view.state, (tx: any) => view.dispatch(tx.addStoredMark(fmark)), true);
         view.focus();
@@ -516,7 +516,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
     get TextView() { return (this.view as any)?.TextView as FormattedTextBox; }
     get TextViewFieldKey() { return this.TextView?.props.fieldKey; }
 
-    
+
 
     @action setActiveHighlight(color: string) { this.activeHighlightColor = color; }
 
@@ -566,7 +566,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
                         if (linkDoc instanceof Doc) {
                             const anchor1 = await Cast(linkDoc.anchor1, Doc);
                             const anchor2 = await Cast(linkDoc.anchor2, Doc);
-                            const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document;
+                            const currentDoc = SelectionManager.Docs().lastElement();
                             if (currentDoc && anchor1 && anchor2) {
                                 if (Doc.AreProtosEqual(currentDoc, anchor1)) {
                                     return StrCast(anchor2.title);
-- 
cgit v1.2.3-70-g09d2


From e0240412990f102523b86e324bc973cd2ed523a1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 14 Sep 2021 22:27:17 -0400
Subject: refactored a bunch of names in MainView.  Fixed scrolling in left
 menu flyout treeview panels.

---
 src/client/views/MainView.scss                     |  62 +---------
 src/client/views/MainView.tsx                      | 126 +++++++++++----------
 src/client/views/collections/CollectionMenu.tsx    |  34 +++---
 .../views/collections/CollectionTreeView.tsx       |  68 +++++------
 src/client/views/collections/TreeView.tsx          |   2 +-
 src/client/views/global/globalCssVariables.scss    |   8 +-
 .../views/global/globalCssVariables.scss.d.ts      |   4 +-
 7 files changed, 130 insertions(+), 174 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 817e45699..4f871f5ec 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -15,8 +15,8 @@
     margin-top: 10px;
 }
 
-.mainContent-div-flyout,
-.mainContent-div {
+.mainView-dockingContent-flyout,
+.mainView-dockingContent {
     position: relative;
     width: 100%;
     height: 100%;
@@ -99,7 +99,7 @@
     }
 }
 
-.mainView-mainContent {
+.mainView-dashboardArea {
     width: 100%;
     height: 100%;
     position: absolute;
@@ -208,7 +208,7 @@
     }
 }
 
-.mainView-menuPanel {
+.mainView-leftMenuPanel {
     min-width: var(--menuPanelWidth);
     background-color: $dark-gray;
     border-right: $standard-border;
@@ -220,60 +220,6 @@
     ::-webkit-scrollbar {
         width: 0;
     }
-
-    .mainView-menuPanel-button {
-        padding: 7px;
-        padding-left: 7px;
-        width: 100%;
-        background: $dark-gray;
-
-        .mainView-menuPanel-button-wrap {
-            width: 45px;
-            /* padding: 5px; */
-            touch-action: none;
-            background: $dark-gray;
-            transform-origin: top left;
-            /* margin-bottom: 5px; */
-            margin-top: 5px;
-            margin-right: 25px;
-            border-radius: 8px;
-
-            &:hover {
-                background: $black;
-                cursor: pointer;
-            }
-        }
-    }
-
-    .mainView-menuPanel-button-label {
-        color: white;
-        margin-left: px;
-        margin-right: 4px;
-        border-radius: 8px;
-        width: 42px;
-        position: relative;
-        text-align: center;
-        font-size: 8px;
-        margin-top: 1px;
-        letter-spacing: normal;
-        padding: 3px;
-        background-color: inherit;
-    }
-
-    .mainView-menuPanel-button-icon {
-        width: auto;
-        height: 35px;
-        padding: 5px;
-    }
-}
-
-.mainView-searchPanel {
-    width: 100%;
-    height: $searchpanel-height;
-    background-color: black;
-    color: white;
-    text-align: center;
-    vertical-align: middle;
 }
 
 .mainView-mainDiv {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b102c9a1f..5bda9f6bf 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -11,9 +11,10 @@ import * as ReactDOM from 'react-dom';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
+import { ScriptField } from '../../fields/ScriptField';
 import { BoolCast, PromiseValue, StrCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocUtils } from '../documents/Documents';
@@ -36,11 +37,12 @@ import { CollectionLinearView } from './collections/collectionLinear';
 import { CollectionMenu } from './collections/CollectionMenu';
 import { CollectionViewType } from './collections/CollectionView';
 import "./collections/TreeView.scss";
+import { ComponentDecorations } from './ComponentDecorations';
 import { ContextMenu } from './ContextMenu';
 import { DictationOverlay } from './DictationOverlay';
 import { DocumentDecorations } from './DocumentDecorations';
 import { GestureOverlay } from './GestureOverlay';
-import { MENU_PANEL_WIDTH, SEARCH_PANEL_HEIGHT } from './global/globalCssVariables.scss';
+import { DASHBOARD_SELECTOR_HEIGHT, LEFT_MENU_WIDTH } from './global/globalCssVariables.scss';
 import { Colors } from './global/globalEnums';
 import { KeyManager } from './GlobalKeyHandler';
 import { InkStrokeProperties } from './InkStrokeProperties';
@@ -48,9 +50,11 @@ import { LightboxView } from './LightboxView';
 import { LinkMenu } from './linking/LinkMenu';
 import "./MainView.scss";
 import { AudioBox } from './nodes/AudioBox';
+import { ButtonType } from './nodes/button/FontIconBox';
 import { DocumentLinksButton } from './nodes/DocumentLinksButton';
 import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
 import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
 import { LinkDocPreview } from './nodes/LinkDocPreview';
 import { RadialMenu } from './nodes/RadialMenu';
@@ -62,10 +66,6 @@ import { PreviewCursor } from './PreviewCursor';
 import { PropertiesView } from './PropertiesView';
 import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
 import { TopBar } from './topbar/TopBar';
-import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
-import { ScriptField } from '../../fields/ScriptField';
-import { ButtonType } from './nodes/button/FontIconBox';
-import { ComponentDecorations } from './ComponentDecorations';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -76,21 +76,32 @@ export class MainView extends React.Component {
     @observable public LastButton: Opt<Doc>;
     @observable private _windowWidth: number = 0;
     @observable private _windowHeight: number = 0;
-    @observable private _panelWidth: number = 0;
-    @observable private _panelHeight: number = 0;
+    @observable private _dashUIWidth: number = 0;   // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
+    @observable private _dashUIHeight: number = 0;  // height of entire main dashboard region including top menu buttons
     @observable private _panelContent: string = "none";
     @observable private _sidebarContent: any = this.userDoc?.sidebar;
-    @observable private _flyoutWidth: number = 0;
+    @observable private _leftMenuFlyoutWidth: number = 0;
 
-    @computed private get topOffset() { return 35 + Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } //TODO remove
-    @computed private get leftOffset() { return this.menuPanelWidth() - 2; }
+    @computed private get dashboardTabHeight() { return 27; } //  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js
+    @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); }
+    @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+    @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; }
+    @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; }
     @computed private get userDoc() { return Doc.UserDoc(); }
     @computed private get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); }
     @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; }
-    @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
-
-    menuPanelWidth = () => Number(MENU_PANEL_WIDTH.replace("px", ""));
-    propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, CurrentUserUtils.propertiesWidth || 0));
+    @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
+
+    topMenuHeight = () => 35;
+    topMenuWidth = returnZero; // value is ignored ...
+    leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", ""));
+    leftMenuHeight = () => this._dashUIHeight;
+    leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth;
+    leftMenuFlyoutHeight = () => this._dashUIHeight;
+    propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0));
+    propertiesHeight = () => this._dashUIHeight;
+    mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth();
+    mainDocViewHeight = () => this._dashUIHeight - this.topMenuHeight();
 
     componentDidMount() {
         document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
@@ -264,11 +275,6 @@ export class MainView extends React.Component {
         Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder);
     }
 
-    getPWidth = () => this._panelWidth - this.propertiesWidth();
-    getPHeight = () => this._panelHeight - (CollectionMenu.Instance?.Pinned ? 35 : 0);
-    getContentsHeight = () => this._panelHeight;
-    getMenuPanelHeight = () => this._panelHeight + (CollectionMenu.Instance?.Pinned ? 35 : 0);
-
     @computed get mainDocView() {
         return <DocumentView key="main"
             Document={this.mainContainer!}
@@ -283,8 +289,8 @@ export class MainView extends React.Component {
             isContentActive={returnTrue}
             removeDocument={undefined}
             ScreenToLocalTransform={Transform.Identity}
-            PanelWidth={this.getPWidth}
-            PanelHeight={this.getPHeight}
+            PanelWidth={this.mainDocViewWidth}
+            PanelHeight={this.mainDocViewHeight}
             focus={DocUtils.DefaultFocus}
             whenChildContentsActiveChanged={emptyFunction}
             bringToFront={emptyFunction}
@@ -298,11 +304,9 @@ export class MainView extends React.Component {
     }
 
     @computed get dockingContent() {
-        return <div key="docking" className={`mainContent-div${this._flyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
-            // style={{ minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, width: `calc(100% - ${this._flyoutWidth + this.propertiesWidth()}px)` }}>
-            // FIXME update with property panel width
+        return <div key="docking" className={`mainView-dockingContent${this._leftMenuFlyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
             style={{
-                minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`,
+                minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                 transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined,
             }}>
             {!this.mainContainer ? (null) : this.mainDocView}
@@ -312,22 +316,21 @@ export class MainView extends React.Component {
     @action
     onPropertiesPointerDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e,
-            action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._panelWidth - e.clientX)) ? false : false),
+            action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false),
             action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)),
-            action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 250) : 0), false);
+            action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false);
     }
 
     @action
     onFlyoutPointerDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e,
-            action(e => (this._flyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
-            () => this._flyoutWidth < 5 && this.closeFlyout(),
+            action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
+            () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(),
             this.closeFlyout);
     }
 
-    flyoutWidthFunc = () => this._flyoutWidth;
-    sidebarScreenToLocal = () => new Transform(0, -this.topOffset, 1);
-    mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftOffset, 0);
+    sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
+    mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
     addDocTabFunc = (doc: Doc, where: string): boolean => {
         return where === "close" ? CollectionDockingView.CloseSplit(doc) :
             doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right");
@@ -335,10 +338,10 @@ export class MainView extends React.Component {
 
 
     @computed get flyout() {
-        return !this._flyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
+        return !this._leftMenuFlyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
             {this.docButtons}
         </div> :
-            <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._flyoutWidth, width: this._flyoutWidth }} >
+            <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._leftMenuFlyoutWidth, width: this._leftMenuFlyoutWidth }} >
                 <div className="mainView-contentArea" >
                     <DocumentView
                         Document={this._sidebarContent.proto || this._sidebarContent}
@@ -352,8 +355,8 @@ export class MainView extends React.Component {
                         rootSelected={returnTrue}
                         removeDocument={returnFalse}
                         ScreenToLocalTransform={this.mainContainerXf}
-                        PanelWidth={this.flyoutWidthFunc}
-                        PanelHeight={this.getContentsHeight}
+                        PanelWidth={this.leftMenuFlyoutWidth}
+                        PanelHeight={this.leftMenuFlyoutHeight}
                         renderDepth={0}
                         isContentActive={returnTrue}
                         scriptContext={CollectionDockingView.Instance?.props.Document}
@@ -371,8 +374,8 @@ export class MainView extends React.Component {
             </div>;
     }
 
-    @computed get menuPanel() {
-        return <div key="menu" className="mainView-menuPanel">
+    @computed get leftMenuPanel() {
+        return <div key="menu" className="mainView-leftMenuPanel">
             <DocumentView
                 Document={Doc.UserDoc().menuStack as Doc}
                 DataDoc={undefined}
@@ -382,8 +385,8 @@ export class MainView extends React.Component {
                 rootSelected={returnTrue}
                 removeDocument={returnFalse}
                 ScreenToLocalTransform={this.sidebarScreenToLocal}
-                PanelWidth={this.menuPanelWidth}
-                PanelHeight={this.getMenuPanelHeight}
+                PanelWidth={this.leftMenuWidth}
+                PanelHeight={this.leftMenuHeight}
                 renderDepth={0}
                 docViewPath={returnEmptyDoclist}
                 focus={DocUtils.DefaultFocus}
@@ -405,7 +408,7 @@ export class MainView extends React.Component {
     @action
     selectMenu = (button: Doc) => {
         const title = StrCast(Doc.GetProto(button).title);
-        const willOpen = !this._flyoutWidth || this._panelContent !== title;
+        const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title;
         this.closeFlyout();
         if (willOpen) {
             switch (this._panelContent = title) {
@@ -422,38 +425,41 @@ 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;
+        const width = this.propertiesWidth() + this._leftMenuFlyoutWidth + this.leftMenuWidth();
+        const transform = this._leftMenuFlyoutWidth ? 'translate(-28px, 0px)' : undefined;
         return <>
-            {this.menuPanel}
+            {this.leftMenuPanel}
             <div key="inner" className={`mainView-innerContent${this.darkScheme ? "-dark" : ""}`}>
                 {this.flyout}
-                <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
+                <div className="mainView-libraryHandle" style={{ display: !this._leftMenuFlyoutWidth ? "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% - ${width}px)`, transform: transform }}>
-                    <CollectionMenu />
+                    <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
 
                     {this.dockingContent}
 
-                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._flyoutWidth ? 0 : this.propertiesWidth() - 1 }}>
+                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._leftMenuFlyoutWidth ? 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()} />}
+                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
                     </div>
                 </div>
             </div>
         </>;
     }
 
-    @computed get mainContent() {
+    @computed get mainDashboardArea() {
         return !this.userDoc ? (null) :
-            <div className="mainView-mainContent" ref={r => {
-                r && new _global.ResizeObserver(action(() => { this._panelWidth = r.getBoundingClientRect().width; this._panelHeight = r.getBoundingClientRect().height; })).observe(r);
+            <div className="mainView-dashboardArea" ref={r => {
+                r && new _global.ResizeObserver(action(() => {
+                    this._dashUIWidth = r.getBoundingClientRect().width;
+                    this._dashUIHeight = r.getBoundingClientRect().height;
+                })).observe(r);
             }} style={{
                 color: this.darkScheme ? "rgb(205,205,205)" : "black",
-                height: `calc(100% - ${this.topOffset - 35}px)`,
+                height: `calc(100% - ${this.topOfDashUI}px)`,
                 width: "100%",
             }} >
                 {this.mainInnerContent}
@@ -461,7 +467,7 @@ export class MainView extends React.Component {
     }
 
     expandFlyout = action((button: Doc) => {
-        this._flyoutWidth = (this._flyoutWidth || 250);
+        this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250);
         this._sidebarContent.proto = button.target as any;
         this.LastButton = button;
         console.log(button.title);
@@ -471,7 +477,7 @@ export class MainView extends React.Component {
         this.LastButton = undefined;
         this._panelContent = "none";
         this._sidebarContent.proto = undefined;
-        this._flyoutWidth = 0;
+        this._leftMenuFlyoutWidth = 0;
     });
 
     remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
@@ -509,8 +515,8 @@ export class MainView extends React.Component {
                     pinToPres={emptyFunction}
                     removeDocument={this.remButtonDoc}
                     ScreenToLocalTransform={this.buttonBarXf}
-                    PanelWidth={this.flyoutWidthFunc}
-                    PanelHeight={this.getContentsHeight}
+                    PanelWidth={this.leftMenuFlyoutWidth}
+                    PanelHeight={this.leftMenuFlyoutHeight}
                     renderDepth={0}
                     focus={DocUtils.DefaultFocus}
                     whenChildContentsActiveChanged={emptyFunction}
@@ -606,14 +612,14 @@ export class MainView extends React.Component {
             <CaptureManager />
             <GroupManager />
             <GoogleAuthenticationManager />
-            <DocumentDecorations PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} boundsLeft={this.leftOffset} boundsTop={this.topOffset} />
-            <ComponentDecorations boundsLeft={this.leftOffset} boundsTop={this.topOffset + 27} /> {/*  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js */}
+            <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
+            <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
             {this.topbar}
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
             <GestureOverlay >
-                {this.mainContent}
+                {this.mainDashboardArea}
             </GestureOverlay>
             <PreviewCursor />
             <TaskCompletionBox />
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 6ffa6c279..8e03b2db2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -42,8 +42,13 @@ import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
 import { Colors } from "../global/globalEnums";
 
+interface CollectionMenuProps {
+    panelHeight: () => number;
+    panelWidth: () => number;
+}
+
 @observer
-export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
+export class CollectionMenu extends AntimodeMenu<CollectionMenuProps>{
     @observable static Instance: CollectionMenu;
 
     @observable SelectedCollection: DocumentView | undefined;
@@ -93,13 +98,10 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
         return new Transform(-translateX, -translateY, 1 / scale);
     }
 
-    panelWidth100 = () => 100;
-    panelHeight35 = () => 35;
-
     @computed get contMenuButtons() {
         trace();
         const selDoc = Doc.UserDoc().contextMenuBtns;
-        return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: "35px" }} >
+        return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: this.props.panelHeight() }} >
             <CollectionLinearView
                 Document={selDoc}
                 DataDoc={undefined}
@@ -122,8 +124,8 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
                 pinToPres={emptyFunction}
                 removeDocument={returnFalse}
                 ScreenToLocalTransform={this.buttonBarXf}
-                PanelWidth={this.panelWidth100}
-                PanelHeight={this.panelHeight35}
+                PanelWidth={this.props.panelWidth}
+                PanelHeight={this.props.panelHeight}
                 renderDepth={0}
                 focus={emptyFunction}
                 whenChildContentsActiveChanged={emptyFunction}
@@ -176,7 +178,7 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
 }
 
-interface CollectionMenuProps {
+interface CollectionViewMenuProps {
     type: CollectionViewType;
     fieldKey: string;
     docView: DocumentView;
@@ -185,7 +187,7 @@ interface CollectionMenuProps {
 const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
 
 @observer
-export class CollectionViewBaseChrome extends React.Component<CollectionMenuProps> {
+export class CollectionViewBaseChrome extends React.Component<CollectionViewMenuProps> {
     //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
 
     get document() { return this.props.docView?.props.Document; }
@@ -628,14 +630,14 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 }
 
 @observer
-export class CollectionDockingChrome extends React.Component<CollectionMenuProps> {
+export class CollectionDockingChrome extends React.Component<CollectionViewMenuProps> {
     render() {
         return (null);
     }
 }
 
 @observer
-export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean, isDoc?: boolean }> {
+export class CollectionFreeFormViewChrome extends React.Component<CollectionViewMenuProps & { isOverlay: boolean, isDoc?: boolean }> {
     public static Instance: CollectionFreeFormViewChrome;
     constructor(props: any) {
         super(props);
@@ -866,7 +868,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 }
 @observer
-export class CollectionStackingViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionStackingViewChrome extends React.Component<CollectionViewMenuProps> {
     @observable private _currentKey: string = "";
     @observable private suggestions: string[] = [];
 
@@ -987,7 +989,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
 
 
 @observer
-export class CollectionSchemaViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionSchemaViewChrome extends React.Component<CollectionViewMenuProps> {
     // private _textwrapAllRows: boolean = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
     get document() { return this.props.docView.props.Document; }
 
@@ -1035,7 +1037,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionMenuPr
 }
 
 @observer
-export class CollectionTreeViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionTreeViewChrome extends React.Component<CollectionViewMenuProps> {
 
     get document() { return this.props.docView.props.Document; }
     get sortAscending() {
@@ -1072,7 +1074,7 @@ export class CollectionTreeViewChrome extends React.Component<CollectionMenuProp
 
 // Enter scroll speed for 3D Carousel 
 @observer
-export class Collection3DCarouselViewChrome extends React.Component<CollectionMenuProps> {
+export class Collection3DCarouselViewChrome extends React.Component<CollectionViewMenuProps> {
     get document() { return this.props.docView.props.Document; }
     @computed get scrollSpeed() {
         return this.document._autoScrollSpeed;
@@ -1113,7 +1115,7 @@ export class Collection3DCarouselViewChrome extends React.Component<CollectionMe
  * Chrome for grid view.
  */
 @observer
-export class CollectionGridViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionGridViewChrome extends React.Component<CollectionViewMenuProps> {
 
     private clicked: boolean = false;
     private entered: boolean = false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 4d62a1af4..624a0bf4a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -267,16 +267,17 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         return hideTitle ? (null) : (this.outlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
     }
 
+    return35 = () => 35;
     @computed get buttonMenu() {
-        const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+        const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
         // To create a multibutton menu add a CollectionLinearView
-        if (menuDoc){
-            
+        if (menuDoc) {
+
             const width: number = NumCast(menuDoc._width, 30);
             const height: number = NumCast(menuDoc._height, 30);
             console.log(menuDoc.title, width, height);
             return (<div className="buttonMenu-docBtn"
-                style = {{width: width, height: height}}>
+                style={{ width: width, height: height }}>
                 <DocumentView
                     Document={menuDoc}
                     DataDoc={menuDoc}
@@ -289,8 +290,8 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                     rootSelected={this.props.isSelected}
                     removeDocument={this.props.removeDocument}
                     ScreenToLocalTransform={Transform.Identity}
-                    PanelWidth={() => 35}
-                    PanelHeight={() => 35}
+                    PanelWidth={this.return35}
+                    PanelHeight={this.return35}
                     renderDepth={this.props.renderDepth + 1}
                     focus={emptyFunction}
                     styleProvider={this.props.styleProvider}
@@ -302,13 +303,14 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                     docRangeFilters={this.props.docRangeFilters}
                     searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} 
+                    ContainingCollectionDoc={undefined}
                 />
             </div>);
         }
     }
 
-    
+    @observable _explainerHeight: number = 0;
+
     @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); }
     @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); }
 
@@ -336,30 +338,30 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const noviceExplainer = this.rootDoc.explainer;
 
         return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
-               <>
-                    {this.titleBar}
-                    <div className="collectionTreeView-container"
-                        style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
-                        onContextMenu={this.onContextMenu}>
-                        {buttonMenu || noviceExplainer ? <div className="documentButtonMenu">
-                            {buttonMenu ? this.buttonMenu : null}
-                            {Doc.UserDoc().noviceMode && noviceExplainer ? 
-                                <div className="documentExplanation">
-                                    {noviceExplainer}
-                                </div>
-                                : null
-                            }
-                        </div> : null}
-                        <div className="collectionTreeView-dropTarget"
-                            style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
-                            onWheel={e => e.stopPropagation()}
-                            onDrop={this.onTreeDrop}
-                            ref={this.createTreeDropTarget}>
-                            <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
-                                {this.treeViewElements}
-                            </ul>
-                        </div >
-                    </div>
-               </>;
+            <>
+                {this.titleBar}
+                <div className="collectionTreeView-container"
+                    style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
+                    onContextMenu={this.onContextMenu}>
+                    {buttonMenu || noviceExplainer ? <div className="documentButtonMenu" ref={action((r: HTMLDivElement) => r && (this._explainerHeight = r.getBoundingClientRect().height))}>
+                        {buttonMenu ? this.buttonMenu : null}
+                        {Doc.UserDoc().noviceMode && noviceExplainer ?
+                            <div className="documentExplanation">
+                                {noviceExplainer}
+                            </div>
+                            : null
+                        }
+                    </div> : null}
+                    <div className="collectionTreeView-dropTarget"
+                        style={{ background: background(), height: `calc(100% - ${this._explainerHeight}px)`, paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
+                        onWheel={e => e.stopPropagation()}
+                        onDrop={this.onTreeDrop}
+                        ref={this.createTreeDropTarget}>
+                        <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
+                            {this.treeViewElements}
+                        </ul>
+                    </div >
+                </div>
+            </>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index aa7b164b0..4fc25752f 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -869,7 +869,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             const childLayout = Doc.Layout(pair.layout);
             const rowHeight = () => {
                 const aspect = Doc.NativeAspect(childLayout);
-                return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]();
+                return (aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]());
             };
             return <TreeView key={child[Id]} ref={r => treeViewRefs.set(child, r ? r : undefined)}
                 document={pair.layout}
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index caa9f4fe5..95bd44c1f 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -54,7 +54,7 @@ $standard-border-radius: 3px;
 $standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
 
 
-$searchpanel-height: 32px;
+$dashboardselector-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
 $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
@@ -63,7 +63,7 @@ $SCHEMA_DIVIDER_WIDTH: 4;
 $MINIMIZED_ICON_SIZE: 24;
 $MAX_ROW_HEIGHT: 44px;
 $DFLT_IMAGE_NATIVE_DIM: 900px;
-$MENU_PANEL_WIDTH: 60px;
+$LEFT_MENU_WIDTH: 60px;
 $TREE_BULLET_WIDTH: 20px;
 
 :export {
@@ -74,8 +74,8 @@ $TREE_BULLET_WIDTH: 20px;
     MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT;
     SEARCH_THUMBNAIL_SIZE: $search-thumnail-size;
     ANTIMODEMENU_HEIGHT: $antimodemenu-height;
-    SEARCH_PANEL_HEIGHT: $searchpanel-height;
+    DASHBOARD_SELECTOR_HEIGHT: $dashboardselector-height;
     DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM;
-    MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH;
+    LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH;
     TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH;
 }
\ No newline at end of file
diff --git a/src/client/views/global/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts
index 11e62e1eb..59c2b3585 100644
--- a/src/client/views/global/globalCssVariables.scss.d.ts
+++ b/src/client/views/global/globalCssVariables.scss.d.ts
@@ -7,9 +7,9 @@ interface IGlobalScss {
     MAX_ROW_HEIGHT: string;
     SEARCH_THUMBNAIL_SIZE: string;
     ANTIMODEMENU_HEIGHT: string;
-    SEARCH_PANEL_HEIGHT: string;
+    DASHBOARD_SELECTOR_HEIGHT: string;
     DFLT_IMAGE_NATIVE_DIM: string;
-    MENU_PANEL_WIDTH: string;
+    LEFT_MENU_WIDTH: string;
     TREE_BULLET_WIDTH: string;
 }
 declare const globalCssVariables: IGlobalScss;
-- 
cgit v1.2.3-70-g09d2


From f71b10a04506cd45ec157a05dbe41217380d814f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 15 Sep 2021 12:14:49 -0400
Subject: fixed documentdecoration resizers.  fixed grouping and added button
 to switch between freeform / group

---
 src/client/views/DocumentDecorations.scss          | 23 +---------------------
 src/client/views/PropertiesButtons.tsx             | 11 +++++++++++
 src/client/views/collections/CollectionMenu.tsx    |  1 -
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 19 ++++++++++++++----
 .../views/nodes/formattedText/RichTextMenu.tsx     |  1 -
 6 files changed, 28 insertions(+), 29 deletions(-)

(limited to 'src/client/views/collections/CollectionMenu.tsx')

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 76b7481a0..a9f50f81b 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -7,27 +7,7 @@ $linkGap: 3px;
   z-index: 2000;
 }
 .documentDecorations-container {
-  z-index: $docDecorations-zindex;
-  position: absolute;
-  top: 0;
-  left: 0;
-  display: grid;
-  grid-template-rows: 20px 8px 1fr 8px;
-  grid-template-columns: 8px 16px 1fr 8px 8px;
-  pointer-events: none;
-
-  .documentDecorations-centerCont {
-    grid-column: 3;
-    background: none;
-  }
-
-  .documentDecorations-selectorButton {
-    pointer-events: auto;
-    height: 15px;
-    width: 15px;
-    left: -20px;
-    top: 20px;
-    display: inline-block;
+    z-index: $docDecorations-zindex;
     position: absolute;
     top: 0;
     left: 0;
@@ -142,7 +122,6 @@ $linkGap: 3px;
     .documentDecorations-bottomRightResizer:hover {
         opacity: 1;
     }
-  }
 
   .documentDecorations-topLeftResizer,
   .documentDecorations-leftResizer,
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index dd737dc9d..e3da7ce2a 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -16,6 +16,8 @@ import { DocumentView } from './nodes/DocumentView';
 import './PropertiesButtons.scss';
 import React = require("react");
 import { Colors } from "./global/globalEnums";
+import { CollectionFreeFormView } from "./collections/collectionFreeForm";
+import { DocumentManager } from "../util/DocumentManager";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -86,6 +88,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed get gridButton() {
         return this.propertyToggleBtn("Grid", "_backgroundGridShow", on => `Display background grid in collection`, on => "border-all");
     }
+    @computed get groupButton() {
+        return this.propertyToggleBtn("Group", "isGroup", on => `Display collection as a Group`, on => "object-group", (dv, doc) => {
+            doc.isGroup = !doc.isGroup;
+            doc.forceActive = doc.isGroup;
+            const dview = dv || DocumentManager.Instance.getFirstDocumentView(doc);
+            (dview?.ComponentView as CollectionFreeFormView)?.updateGroupBounds?.()
+        });
+    }
     @computed get snapButton() {
         return this.propertyToggleBtn("Snap\xA0Lines", "showSnapLines", on => `Display snapping lines when objects are dragged`, on => "border-all", undefined, true);
     }
@@ -219,6 +229,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 {toggle(this.maskButton, { display: !isInk ? "none" : "" })}
                 {toggle(this.chromeButton, { display: !isCollection || isNovice ? "none" : "" })}
                 {toggle(this.gridButton, { display: !isCollection ? "none" : "" })}
+                {toggle(this.groupButton, { display: !isCollection ? "none" : "" })}
                 {toggle(this.snapButton, { display: !isCollection ? "none" : "" })}
                 {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })}
                 {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 8e03b2db2..2c2d5dc75 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -99,7 +99,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps>{
     }
 
     @computed get contMenuButtons() {
-        trace();
         const selDoc = Doc.UserDoc().contextMenuBtns;
         return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: this.props.panelHeight() }} >
             <CollectionLinearView
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index bc02c44f0..5c9c8063b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -166,7 +166,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
         !Doc.UserDoc().noviceMode && subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" });
         subItems.push({ description: "Grid", event: () => func(CollectionViewType.Grid), icon: "th-list" });
 
-        if (!Doc.IsSystem(this.rootDoc) && !this.rootDoc.annotationOn) {
+        if (!Doc.IsSystem(this.rootDoc) && !this.rootDoc.isGroup && !this.rootDoc.annotationOn) {
             const existingVm = ContextMenu.Instance.findByDescription(category);
             const catItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
             catItems.push({ description: "Add a Perspective...", addDivider: true, noexpand: true, subitems: subItems, icon: "eye" });
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c8561d901..ef127d328 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -183,7 +183,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     addDocument = (newBox: Doc | Doc[]) => {
         let retVal = false;
         if (newBox instanceof Doc) {
-            if (retVal = this.props.addDocument?.(newBox) || false) {
+            if (retVal = (this.props.addDocument?.(newBox) || false)) {
                 this.bringToFront(newBox);
                 this.updateCluster(newBox);
             }
@@ -1236,6 +1236,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             { fireImmediately: true, name: "doLayout" });
 
         this._marqueeRef.current?.addEventListener("dashDragAutoScroll", this.onDragAutoScroll as any);
+        this.rootDoc.isGroup && this.updateGroupBounds()
     }
 
     componentWillUnmount() {
@@ -1327,8 +1328,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         !options && ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
         const mores = ContextMenu.Instance.findByDescription("More...");
         const moreItems = mores && "subitems" in mores ? mores.subitems : [];
-        moreItems.push({ description: "Export collection", icon: "download", event: async () => Doc.Zip(this.props.Document) });
-        moreItems.push({ description: "Import exported collection", icon: "upload", event: ({ x, y }) => this.importDocument(x, y) });
+        if (!Doc.UserDoc().noviceMode) {
+            moreItems.push({ description: "Export collection", icon: "download", event: async () => Doc.Zip(this.props.Document) });
+            moreItems.push({ description: "Import exported collection", icon: "upload", event: ({ x, y }) => this.importDocument(x, y) });
+        }
         !mores && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "eye" });
     }
 
@@ -1484,6 +1487,14 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         return wscale < hscale ? wscale : hscale;
     }
 
+    private groupDropDisposer?: DragManager.DragDropDisposer;
+    protected createGroupEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view
+        this.groupDropDisposer?.();
+        if (ele) {
+            this.groupDropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc, this.onInternalPreDrop.bind(this));
+        }
+    }
+
     render() {
         TraceMobx();
         const clientRect = this._mainCont?.getBoundingClientRect();
@@ -1527,7 +1538,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 </div>}
 
             {this.props.Document._isGroup && SnappingManager.GetIsDragging() && (this.ChildDrag || this.props.layerProvider?.(this.props.Document) === false) ?
-                <div className="collectionFreeForm-groupDropper" ref={this.createDashEventsTarget} style={{
+                <div className="collectionFreeForm-groupDropper" ref={this.createGroupEventsTarget} style={{
                     width: this.ChildDrag ? "10000" : "100%",
                     height: this.ChildDrag ? "10000" : "100%",
                     left: this.ChildDrag ? "-5000" : 0,
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 86f2810ab..9904a7939 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -147,7 +147,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
             const path = (this.view.state.selection.$from as any).path;
             for (let i = path.length - 3; i < path.length && i >= 0; i -= 3) {
                 if (path[i]?.type === this.view.state.schema.nodes.paragraph || path[i]?.type === this.view.state.schema.nodes.heading) {
-                    console.log(path[i].attrs);
                     return path[i].attrs.strong;
                 }
             }
-- 
cgit v1.2.3-70-g09d2

