DEV: adds a loading property to d-button (#9072)

Usage:

```
{{d-button icon="times" label="foo.bar" isLoading=true}}
```

Note that  a button loading without an icon will shrink text size to prevent button to jump in size.

A button while loading is disabled.
This commit is contained in:
Joffrey JAFFEUX 2020-03-30 23:17:00 +02:00 committed by GitHub
parent 2a2555e598
commit 5b6cdd6fb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 4 deletions

View File

@ -1,4 +1,5 @@
import { notEmpty, empty, equal } from "@ember/object/computed";
import { computed } from "@ember/object";
import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators";
import DiscourseURL from "discourse/lib/url";
@ -11,17 +12,36 @@ export default Component.extend({
type: "button",
isLoading: computed({
set(key, value) {
this.set("forceDisabled", value);
return value;
}
}),
tagName: "button",
classNameBindings: ["btnLink::btn", "btnLink", "noText", "btnType"],
classNameBindings: [
"isLoading:is-loading",
"btnLink::btn",
"btnLink",
"noText",
"btnType"
],
attributeBindings: [
"form",
"disabled",
"isDisabled:disabled",
"translatedTitle:title",
"translatedLabel:aria-label",
"tabindex",
"type"
],
isDisabled: computed("disabled", "forceDisabled", function() {
return this.forceDisabled || this.disabled;
}),
forceDisabled: false,
btnIcon: notEmpty("icon"),
btnLink: equal("display", "link"),

View File

@ -1,5 +1,13 @@
{{#if icon}}
{{d-icon icon}}
{{#if isLoading}}
{{d-icon "spinner" class="loading-icon"}}
{{else}}
{{d-icon icon}}
{{/if}}
{{else}}
{{#if isLoading}}
{{d-icon "spinner" class="loading-icon"}}
{{/if}}
{{/if}}
{{#if translatedLabel}}

View File

@ -67,6 +67,31 @@
}
cursor: not-allowed;
}
.loading-container {
display: none;
margin: 0 6.75px 0 0;
}
&.is-loading {
&.btn-text {
.d-button-label {
font-size: $font-down-2;
}
&.btn-small {
.loading-icon {
font-size: $font-down-1;
margin-right: 0.2em;
}
}
}
.loading-icon {
-webkit-animation: rotate-forever 1s infinite linear, fadein 1s;
animation: rotate-forever 1s infinite linear, fadein 1s;
}
}
}
.btn.hidden {

View File

@ -198,7 +198,8 @@ module SvgSprite
"user-shield",
"user-times",
"users",
"wrench"
"wrench",
"spinner"
])
FA_ICON_MAP = { 'far fa-' => 'far-', 'fab fa-' => 'fab-', 'fas fa-' => '', 'fa-' => '' }

View File

@ -54,3 +54,49 @@ componentTest("link-styled button", {
);
}
});
componentTest("isLoading button", {
template: "{{d-button isLoading=isLoading}}",
beforeEach() {
this.set("isLoading", true);
},
test(assert) {
assert.ok(
find("button.is-loading .spinner").length,
"it has a spinner showing"
);
assert.ok(
find("button[disabled]").length,
"while loading the button is disabled"
);
this.set("isLoading", false);
assert.notOk(
find("button .spinner").length,
"it doesn't have a spinner showing"
);
assert.ok(
find("button:not([disabled])").length,
"while not loading the button is enabled"
);
}
});
componentTest("disabled button", {
template: "{{d-button disabled=disabled}}",
beforeEach() {
this.set("disabled", true);
},
test(assert) {
assert.ok(find("button[disabled]").length, "the button is disabled");
this.set("disabled", false);
assert.ok(find("button:not([disabled])").length, "the button is enabled");
}
});