DEV: allows buttons to define aria-label (#9747)

DEV: allows buttons to define aria-label (#9747)

diff --git a/app/assets/javascripts/discourse/app/components/d-button.js b/app/assets/javascripts/discourse/app/components/d-button.js
index 4df816a..ad4d32a 100644
--- a/app/assets/javascripts/discourse/app/components/d-button.js
+++ b/app/assets/javascripts/discourse/app/components/d-button.js
@@ -5,12 +5,17 @@ import discourseComputed from "discourse-common/utils/decorators";
 import DiscourseURL from "discourse/lib/url";
 
 export default Component.extend({
+  tagName: "button",
   // subclasses need this
   layoutName: "components/d-button",
-
   form: null,
-
   type: "button",
+  title: null,
+  translatedTitle: null,
+  label: null,
+  translatedLabel: null,
+  ariaLabel: null,
+  translatedAriaLabel: null,
 
   isLoading: computed({
     set(key, value) {
@@ -19,7 +24,6 @@ export default Component.extend({
     }
   }),
 
-  tagName: "button",
   classNameBindings: [
     "isLoading:is-loading",
     "btnLink::btn",
@@ -30,8 +34,8 @@ export default Component.extend({
   attributeBindings: [
     "form",
     "isDisabled:disabled",
-    "translatedTitle:title",
-    "translatedLabel:aria-label",
+    "computedTitle:title",
+    "computedAriaLabel:aria-label",
     "tabindex",
     "type"
   ],
@@ -46,7 +50,7 @@ export default Component.extend({
 
   btnLink: equal("display", "link"),
 
-  @discourseComputed("icon", "translatedLabel")
+  @discourseComputed("icon", "computedLabel")
   btnType(icon, translatedLabel) {
     if (icon) {
       return translatedLabel ? "btn-icon-text" : "btn-icon";
@@ -55,28 +59,25 @@ export default Component.extend({
     }
   },
 
-  noText: empty("translatedLabel"),
+  noText: empty("computedLabel"),
 
-  @discourseComputed("title")
-  translatedTitle: {
-    get() {
-      if (this._translatedTitle) return this._translatedTitle;
-      if (this.title) return I18n.t(this.title);
-    },
-    set(value) {
-      return (this._translatedTitle = value);
-    }
+  @discourseComputed("title", "translatedTitle")
+  computedTitle(title, translatedTitle) {
+    if (this.title) return I18n.t(title);
+    return translatedTitle;
   },
 
-  @discourseComputed("label")
-  translatedLabel: {
-    get() {
-      if (this._translatedLabel) return this._translatedLabel;
-      if (this.label) return I18n.t(this.label);
-    },
-    set(value) {
-      return (this._translatedLabel = value);
-    }
+  @discourseComputed("label", "translatedLabel")
+  computedLabel(label, translatedLabel) {
+    if (this.label) return I18n.t(label);
+    return translatedLabel;
+  },
+
+  @discourseComputed("ariaLabel", "translatedAriaLabel", "computedLabel")
+  computedAriaLabel(ariaLabel, translatedAriaLabel, computedLabel) {
+    if (ariaLabel) return I18n.t(ariaLabel);
+    if (translatedAriaLabel) return translatedAriaLabel;
+    return computedLabel;
   },
 
   click() {
diff --git a/app/assets/javascripts/discourse/app/lib/register-topic-footer-button.js b/app/assets/javascripts/discourse/app/lib/register-topic-footer-button.js
index c2dd9eb..ecac09a 100644
--- a/app/assets/javascripts/discourse/app/lib/register-topic-footer-button.js
+++ b/app/assets/javascripts/discourse/app/lib/register-topic-footer-button.js
@@ -28,6 +28,10 @@ export function registerTopicFooterButton(button) {
     label: null,
     translatedLabel: null,
 
+    // local key path for aria label
+    ariaLabel: null,
+    translatedAriaLabel: null,
+
     // is this button disaplyed in the mobile dropdown or as an inline button ?
     dropdown: false,
 
@@ -98,6 +102,15 @@ export function getTopicFooterButtons() {
             ? I18n.t(label)
             : _compute(button, "translatedLabel");
 
+          const ariaLabel = _compute(button, "ariaLabel");
+          if (ariaLabel) {
+            discourseComputedButon.ariaLabel = I18n.t(ariaLabel);
+          } else {
+            const translatedAriaLabel = _compute(button, "translatedAriaLabel");
+            discourseComputedButon.ariaLabel =
+              translatedAriaLabel || discourseComputedButon.label;
+          }
+
           const title = _compute(button, "title");
           discourseComputedButon.title = title
             ? I18n.t(title)
diff --git a/app/assets/javascripts/discourse/app/templates/components/d-button.hbs b/app/assets/javascripts/discourse/app/templates/components/d-button.hbs
index 6c9ed40..10d12b4 100644
--- a/app/assets/javascripts/discourse/app/templates/components/d-button.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/d-button.hbs
@@ -10,8 +10,8 @@
   {{/if}}
 {{/if}}
 
-{{#if translatedLabel}}
-  <span class="d-button-label">{{html-safe translatedLabel}}{{#if ellipsis}}&hellip;{{/if}}</span>
+{{#if computedLabel}}
+  <span class="d-button-label">{{html-safe computedLabel}}{{#if ellipsis}}&hellip;{{/if}}</span>
 {{/if}}
 
 {{yield}}
diff --git a/app/assets/javascripts/discourse/app/templates/components/topic-footer-buttons.hbs b/app/assets/javascripts/discourse/app/templates/components/topic-footer-buttons.hbs
index 766ae9b..007ec9c 100644
--- a/app/assets/javascripts/discourse/app/templates/components/topic-footer-buttons.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/topic-footer-buttons.hbs
@@ -29,6 +29,7 @@
       icon=button.icon
       translatedLabel=button.label
       translatedTitle=button.title
+      translatedAriaLabel=button.ariaLabel
       disabled=button.disabled}}
   {{/each}}
 
diff --git a/test/javascripts/components/d-button-test.js b/test/javascripts/components/d-button-test.js
index 5b0bdeb..1d85d92 100644
--- a/test/javascripts/components/d-button-test.js
+++ b/test/javascripts/components/d-button-test.js
@@ -100,3 +100,75 @@ componentTest("disabled button", {
     assert.ok(find("button:not([disabled])").length, "the button is enabled");
   }
 });
+
+componentTest("aria-label", {
+  template:
+    "{{d-button ariaLabel=ariaLabel translatedAriaLabel=translatedAriaLabel}}",
+
+  beforeEach() {
+    I18n.translations[I18n.locale].js.test = { fooAriaLabel: "foo" };
+  },
+
+  test(assert) {
+    this.set("ariaLabel", "test.fooAriaLabel");
+
+    assert.equal(
+      find("button")[0].getAttribute("aria-label"),
+      I18n.t("test.fooAriaLabel")
+    );
+
+    this.setProperties({
+      ariaLabel: null,
+      translatedAriaLabel: "bar"
+    });
+
+    assert.equal(find("button")[0].getAttribute("aria-label"), "bar");
+  }
+});
+
+componentTest("title", {
+  template: "{{d-button title=title translatedTitle=translatedTitle}}",
+
+  beforeEach() {
+    I18n.translations[I18n.locale].js.test = { fooTitle: "foo" };
+  },
+
+  test(assert) {
+    this.set("title", "test.fooTitle");
+    assert.equal(
+      find("button")[0].getAttribute("title"),
+      I18n.t("test.fooTitle")
+    );
+
+    this.setProperties({
+      title: null,
+      translatedTitle: "bar"
+    });
+
+    assert.equal(find("button")[0].getAttribute("title"), "bar");
+  }
+});
+
+componentTest("label", {
+  template: "{{d-button label=label translatedLabel=translatedLabel}}",
+
+  beforeEach() {
+    I18n.translations[I18n.locale].js.test = { fooLabel: "foo" };
+  },
+
+  test(assert) {
+    this.set("label", "test.fooLabel");
+
+    assert.equal(
+      find("button .d-button-label").text(),
+      I18n.t("test.fooLabel")
+    );
+
+    this.setProperties({
+      label: null,
+      translatedLabel: "bar"
+    });
+
+    assert.equal(find("button .d-button-label").text(), "bar");
+  }
+});

GitHub sha: 286b4e53

This commit appears in #9747 which was approved by eviltrout. It was merged by jjaffeux.