]> BookStack Code Mirror - bookstack/commitdiff
Polished up code editor design
authorDan Brown <redacted>
Mon, 20 Jun 2022 16:11:34 +0000 (17:11 +0100)
committerDan Brown <redacted>
Mon, 20 Jun 2022 16:11:34 +0000 (17:11 +0100)
resources/js/components/code-editor.js
resources/sass/_components.scss
resources/views/pages/parts/code-editor.blade.php

index 4ee3531c58a7da957079a7a9ffb6c46aaaaf9c4c..27ff56395d1af49968014407f77c31d1b96e6c3c 100644 (file)
@@ -33,10 +33,11 @@ class CodeEditor {
         onSelect(this.languageLinks, event => {
             const language = event.target.dataset.lang;
             this.languageInput.value = language;
-            this.updateEditorMode(language);
+            this.languageInputChange(language);
         });
 
         onEnterPress(this.languageInput, e => this.save());
+        this.languageInput.addEventListener('input', e => this.languageInputChange(this.languageInput.value));
         onSelect(this.saveButton, e => this.save());
 
         onChildEvent(this.historyList, 'button', 'click', (event, elem) => {
@@ -60,7 +61,7 @@ class CodeEditor {
         this.callback = callback;
 
         this.show()
-            .then(() => this.updateEditorMode(language))
+            .then(() => this.languageInputChange(language))
             .then(() => window.importVersioned('code'))
             .then(Code => Code.setContent(this.editor, code));
     }
@@ -90,6 +91,22 @@ class CodeEditor {
         Code.setMode(this.editor, language, this.editor.getValue());
     }
 
+    languageInputChange(language) {
+        this.updateEditorMode(language);
+        const inputLang = language.toLowerCase();
+        let matched = false;
+
+        for (const link of this.languageLinks) {
+            const lang = link.dataset.lang.toLowerCase().trim();
+            const isMatch = inputLang && lang.startsWith(inputLang);
+            link.classList.toggle('active', isMatch);
+            if (isMatch && !matched) {
+                link.scrollIntoView({block: "center", behavior: "smooth"});
+                matched = true;
+            }
+        }
+    }
+
     loadHistory() {
         this.history = JSON.parse(window.sessionStorage.getItem(this.historyKey) || '{}');
         const historyKeys = Object.keys(this.history).reverse();
index aba79bac289e5d1f7f89da411b3f31da526279ad..c0a418a8e36b3b31ecd93925ce47b77435c65410 100644 (file)
@@ -1,3 +1,4 @@
+
 // System wide notifications
 [notification] {
   position: fixed;
   }
 }
 
-.popup-footer button, .popup-header-close {
-  position: absolute;
-  top: 0;
-  right: 0;
+.popup-header button, .popup-footer button {
   margin: 0;
-  height: 40px;
   border-radius: 0;
   box-shadow: none;
-  &:active {
-    outline: 0;
+  color: #FFF;
+  padding: $-xs $-m;
+}
+
+.popup-header button:not(.popup-header-close) {
+  font-size: 0.8rem;
+}
+
+.popup-header button:hover {
+    background-color: rgba(255, 255, 255, 0.1);
+}
+
+.popup-footer {
+  justify-content: end;
+  button {
+    padding: 10px $-m;
   }
 }
+
 .popup-header-close {
-  background-color: transparent;
   border: 0;
   color: #FFF;
   font-size: 16px;
-  padding: 0 $-m;
+  cursor: pointer;
+  svg {
+    margin-right: 0;
+  }
 }
 
 .popup-header, .popup-footer {
-  display: block !important;
+  display: flex;
   position: relative;
   height: 40px;
-  flex: none !important;
+  flex: 0;
   .popup-title {
     color: #FFF;
+    margin-right: auto;
     padding: 8px $-m;
   }
   &.flex-container-row {
@@ -633,11 +648,15 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
 }
 
 .code-editor .CodeMirror {
-  height: 400px;
+  height: auto;
+  min-height: 50vh;
+  border-bottom: 0;
 }
 
 .code-editor .lang-options {
   overflow-y: scroll;
+  flex-basis: 200px;
+  flex-grow: 1;
 }
 
 .code-editor .lang-options button {
@@ -648,7 +667,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   text-align: left;
   font-family: $mono;
   font-size: 0.7rem;
-  &:hover {
+  &:hover, &.active {
     background-color: var(--color-primary-light);
     color: var(--color-primary);
   }
@@ -659,32 +678,31 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
   width: 100%;
   color: var(--color-primary);
   padding: $-xxs $-m;
+  margin-bottom: 0;
 }
 
 .code-editor-language-list {
+  position: relative;
   flex-basis: 200px;
-  border-right: 1px solid #DDD;
-  box-shadow: $bs-card;
+  z-index: 2;
+  align-items: stretch;
 }
 
 .code-editor-language-list input {
   border-radius: 0;
   border: 0;
   border-bottom: 1px solid #DDD;
+  padding: $-xs $-m;
 }
 
 .code-editor-main {
   flex: 1;
-  height: 100%;
-  overflow-y: scroll;
-}
-
-@include smaller-than($m) {
-  .code-editor .lang-options {
+  min-width: 0;
+  .CodeMirror {
+    margin-bottom: 0;
+    z-index: 1;
     max-width: 100%;
-  }
-  .code-editor .CodeMirror {
-    height: 200px;
+    width: 100%;
   }
 }
 
index 676d3799f595739280581154ca4bde929a10482a..2224209b1d327605c2acfd88e89276ff854a289f 100644 (file)
@@ -4,17 +4,17 @@
 
             <div class="popup-header flex-container-row primary-background">
                 <div class="popup-title">{{ trans('components.code_editor') }}</div>
-                <div component="dropdown" refs="code-editor@historyDropDown" class="block">
-                    <button refs="dropdown@toggle" class="text-small">
+                <div component="dropdown" refs="code-editor@historyDropDown" class="flex-container-row">
+                    <button refs="dropdown@toggle">
                         <span>@icon('history')</span>
                         <span>{{ trans('components.code_session_history') }}</span>
                     </button>
                     <ul refs="dropdown@menu code-editor@historyList" class="dropdown-menu"></ul>
                 </div>
-                <button class="popup-header-close" refs="popup@hide">x</button>
+                <button class="popup-header-close" refs="popup@hide">@icon('close')</button>
             </div>
 
-            <div class="flex-container-row flex-fill gap-m">
+            <div class="flex-container-row flex-fill">
                 <div class="code-editor-language-list flex-container-column flex-fill">
                     <label for="code-editor-language">{{ trans('components.code_language') }}</label>
                     <input refs="code-editor@languageInput" id="code-editor-language" type="text">
@@ -49,7 +49,7 @@
                     </div>
                 </div>
 
-                <div class="code-editor-main">
+                <div class="code-editor-main flex-fill">
                     <textarea refs="code-editor@editor"></textarea>
                 </div>