UX: Prevent some composer buttons from receiving focus (#12719)

UX: Prevent some composer buttons from receiving focus (#12719)

diff --git a/app/assets/javascripts/discourse/app/components/d-button.js b/app/assets/javascripts/discourse/app/components/d-button.js
index da93f36..5c76b4e 100644
--- a/app/assets/javascripts/discourse/app/components/d-button.js
+++ b/app/assets/javascripts/discourse/app/components/d-button.js
@@ -20,6 +20,7 @@ export default Component.extend({
   ariaControls: null,
   translatedAriaLabel: null,
   forwardEvent: false,
+  preventFocus: false,
 
   isLoading: computed({
     set(key, value) {
@@ -133,4 +134,10 @@ export default Component.extend({
 
     return false;
   },
+
+  mouseDown(event) {
+    if (this.preventFocus) {
+      event.preventDefault();
+    }
+  },
 });
diff --git a/app/assets/javascripts/discourse/app/components/d-editor.js b/app/assets/javascripts/discourse/app/components/d-editor.js
index 01a09f4..857a20f 100644
--- a/app/assets/javascripts/discourse/app/components/d-editor.js
+++ b/app/assets/javascripts/discourse/app/components/d-editor.js
@@ -81,22 +81,24 @@ class Toolbar {
     ];
 
     this.addButton({
-      trimLeading: true,
       id: "bold",
       group: "fontStyles",
       icon: "bold",
       label: getButtonLabel("composer.bold_label", "B"),
       shortcut: "B",
+      preventFocus: true,
+      trimLeading: true,
       perform: (e) => e.applySurround("**", "**", "bold_text"),
     });
 
     this.addButton({
-      trimLeading: true,
       id: "italic",
       group: "fontStyles",
       icon: "italic",
       label: getButtonLabel("composer.italic_label", "I"),
       shortcut: "I",
+      preventFocus: true,
+      trimLeading: true,
       perform: (e) => e.applySurround("*", "*", "italic_text"),
     });
 
@@ -105,6 +107,7 @@ class Toolbar {
         id: "link",
         group: "insertions",
         shortcut: "K",
+        preventFocus: true,
         trimLeading: true,
         sendAction: (event) => this.context.send("showLinkModal", event),
       });
@@ -115,6 +118,7 @@ class Toolbar {
       group: "insertions",
       icon: "quote-right",
       shortcut: "Shift+9",
+      preventFocus: true,
       perform: (e) =>
         e.applyList("> ", "blockquote_text", {
           applyEmptyLines: true,
@@ -126,6 +130,8 @@ class Toolbar {
       id: "code",
       group: "insertions",
       shortcut: "Shift+C",
+      preventFocus: true,
+      trimLeading: true,
       action: (...args) => this.context.send("formatCode", args),
     });
 
@@ -135,6 +141,7 @@ class Toolbar {
       icon: "list-ul",
       shortcut: "Shift+8",
       title: "composer.ulist_title",
+      preventFocus: true,
       perform: (e) => e.applyList("* ", "list_item"),
     });
 
@@ -144,6 +151,7 @@ class Toolbar {
       icon: "list-ol",
       shortcut: "Shift+7",
       title: "composer.olist_title",
+      preventFocus: true,
       perform: (e) =>
         e.applyList(
           (i) => (!i ? "1. " : `${parseInt(i, 10) + 1}. `),
@@ -158,6 +166,7 @@ class Toolbar {
         icon: "exchange-alt",
         shortcut: "Shift+6",
         title: "composer.toggle_direction",
+        preventFocus: true,
         perform: (e) => e.toggleDirection(),
       });
     }
@@ -180,6 +189,7 @@ class Toolbar {
       perform: button.perform || function () {},
       trimLeading: button.trimLeading,
       popupMenu: button.popupMenu || false,
+      preventFocus: button.preventFocus || false,
     };
 
     if (button.sendAction) {
@@ -638,18 +648,20 @@ export default Component.extend({
     }
   },
 
-  _selectText(from, length) {
+  _selectText(from, length, opts = { scroll: true }) {
     next(() => {
       const textarea = this.element.querySelector("textarea.d-editor-input");
       const $textarea = $(textarea);
-      const oldScrollPos = $textarea.scrollTop();
-      if (!this.capabilities.isIOS || safariHacksDisabled()) {
-        $textarea.focus();
-      }
       textarea.selectionStart = from;
       textarea.selectionEnd = from + length;
       $textarea.trigger("change");
-      $textarea.scrollTop(oldScrollPos);
+      if (opts.scroll) {
+        const oldScrollPos = $textarea.scrollTop();
+        if (!this.capabilities.isIOS || safariHacksDisabled()) {
+          $textarea.focus();
+        }
+        $textarea.scrollTop(oldScrollPos);
+      }
     });
   },
 
@@ -1046,7 +1058,8 @@ export default Component.extend({
       const selected = this._getSelected(button.trimLeading);
       const toolbarEvent = {
         selected,
-        selectText: (from, length) => this._selectText(from, length),
+        selectText: (from, length) =>
+          this._selectText(from, length, { scroll: false }),
         applySurround: (head, tail, exampleKey, opts) =>
           this._applySurround(selected, head, tail, exampleKey, opts),
         applyList: (head, exampleKey, opts) =>
diff --git a/app/assets/javascripts/discourse/app/templates/components/composer-toggles.hbs b/app/assets/javascripts/discourse/app/templates/components/composer-toggles.hbs
index 4325365..ac9ac22 100644
--- a/app/assets/javascripts/discourse/app/templates/components/composer-toggles.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/composer-toggles.hbs
@@ -7,7 +7,9 @@
       icon="bars"
       action=toggleToolbar
       title=toggleToolbarTitle
-      ariaLabel=toggleToolbarTitle}}
+      ariaLabel=toggleToolbarTitle
+      preventFocus=true
+    }}
   {{/if}}
 
   {{d-button
@@ -15,7 +17,8 @@
     icon=toggleIcon
     action=toggleComposer
     title=toggleTitle
-    ariaLabel=toggleTitle}}
+    ariaLabel=toggleTitle
+  }}
 
   {{#unless site.mobileView}}
     {{d-button
@@ -23,6 +26,7 @@
       icon=fullscreenIcon
       action=toggleFullscreen
       title=fullscreenTitle
-      ariaLabel=fullscreenTitle}}
+      ariaLabel=fullscreenTitle
+    }}
   {{/unless}}
 </div>
diff --git a/app/assets/javascripts/discourse/app/templates/components/d-editor.hbs b/app/assets/javascripts/discourse/app/templates/components/d-editor.hbs
index 787f198..e9df77f 100644
--- a/app/assets/javascripts/discourse/app/templates/components/d-editor.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/d-editor.hbs
@@ -22,7 +22,9 @@
               translatedTitle=b.title
               label=b.label
               icon=b.icon
-              class=b.className}}
+              class=b.className
+              preventFocus=b.preventFocus
+            }}
           {{/if}}
         {{/each}}
 
diff --git a/app/assets/javascripts/select-kit/addon/components/composer-actions.js b/app/assets/javascripts/select-kit/addon/components/composer-actions.js
index 7961e83..4ac26b9 100644
--- a/app/assets/javascripts/select-kit/addon/components/composer-actions.js
+++ b/app/assets/javascripts/select-kit/addon/components/composer-actions.js
@@ -35,6 +35,7 @@ export default DropdownSelectBoxComponent.extend({
     icon: "iconForComposerAction",
     filterable: false,
     showFullTitle: false,
+    preventHeaderFocus: true,
   },
 
   iconForComposerAction: computed("action", "whisper", "noBump", function () {
diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit.js b/app/assets/javascripts/select-kit/addon/components/select-kit.js
index 2a4d276..3551ce7 100644
--- a/app/assets/javascripts/select-kit/addon/components/select-kit.js
+++ b/app/assets/javascripts/select-kit/addon/components/select-kit.js
@@ -957,7 +957,7 @@ export default Component.extend(
         const input = this.getFilterInput();
         if (!forceHeader && input) {
           input.focus({ preventScroll: true });
-        } else {
+        } else if (!this.selectKit.options.preventHeaderFocus) {
           const headerContainer = this.getHeader();
           headerContainer && headerContainer.focus({ preventScroll: true });
         }
diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js
index 31f9efb..26f8b81 100644

[... diff too long, it was truncated ...]

GitHub sha: 35f977f8

This commit appears in #12719 which was approved by eviltrout and jjaffeux. It was merged by pmusaraj.