Skip to content

Commit

Permalink
[EC-556] refactor cl button (#3537)
Browse files Browse the repository at this point in the history
* [EC-556] feat: convert button into component

* [EC-556] feat: implement loading state

* [EC-556] feat: remove loading from submit button

* [EC-556] fix: add missing import

* [EC-556] fix: disabling button using regular attribute

* [EC-556] fix: missing loading input in story templates

* [EC-556] feat: remove and replace submit button

* Fix packaging on Build Web workflow (#3613)

(cherry picked from commit 67c447d)

* [EC-556] fix: replaced buttons should be primary

Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
  • Loading branch information
coroiu and vgrassia authored Sep 27, 2022
1 parent b5de573 commit cd7c9bf
Show file tree
Hide file tree
Showing 26 changed files with 180 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@

<div class="tw-mb-3 tw-flex">
<ng-container *ngIf="!accountCreated">
<bit-submit-button [loading]="form.loading">{{ "createAccount" | i18n }}</bit-submit-button>
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "createAccount" | i18n }}
</button>
<a
bitButton
buttonType="secondary"
Expand All @@ -126,7 +128,9 @@
</a>
</ng-container>
<ng-container *ngIf="accountCreated">
<bit-submit-button [loading]="form.loading">{{ "logIn" | i18n }}</bit-submit-button>
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "logIn" | i18n }}
</button>
</ng-container>
</div>
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ <h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "paymentType" | i18n }}</h2
</div>

<div class="tw-flex tw-space-x-2">
<bit-submit-button [loading]="form.loading">{{ "startTrial" | i18n }}</bit-submit-button>
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "startTrial" | i18n }}
</button>

<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ <h1>{{ "myOrganization" | i18n }}</h1>
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "save" | i18n }}
</bit-submit-button>
</button>
</form>
<ng-container *ngIf="canUseApi">
<div class="secondary-header border-0 mb-0">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ <h1 class="modal-title" id="enrollMasterPasswordResetTitle">
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
</div>
<div class="modal-footer">
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
<button
bitButton
buttonType="secondary"
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/reports/pages/breach-report.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ <h1>{{ "dataBreachReport" | i18n }}</h1>
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "checkBreaches" | i18n }}
</bit-submit-button>
</button>
</form>
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
</div>
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
<bit-submit-button [loading]="loading" (click)="load()">
<button type="submit" buttonType="primary" bitButton [loading]="loading" (click)="load()">
{{ "checkExposedPasswords" | i18n }}
</bit-submit-button>
</button>
<div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noExposedPasswords" | i18n }}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/settings/change-kdf.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ <h1>{{ "encKeySettings" | i18n }}</h1>
</div>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "changeKdf" | i18n }}
</bit-submit-button>
</button>
</form>
4 changes: 2 additions & 2 deletions apps/web/src/app/settings/change-password.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ <h1>{{ "changeMasterPassword" | i18n }}</h1>
</a>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "changeMasterPassword" | i18n }}
</bit-submit-button>
</button>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,15 @@ <h3>
</div>
</div>
<div class="modal-footer">
<bit-submit-button [loading]="loading || form.loading" [disabled]="readOnly">
<button
type="submit"
buttonType="primary"
bitButton
[loading]="loading || form.loading"
[disabled]="readOnly"
>
{{ "save" | i18n }}
</bit-submit-button>
</button>
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
{{ "cancel" | i18n }}
</button>
Expand Down
12 changes: 9 additions & 3 deletions apps/web/src/app/settings/organization-plans.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,15 @@ <h2 class="spaced-header mb-4">
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
</div>
<div class="mt-4">
<bit-submit-button [loading]="form.loading" [disabled]="!formGroup.valid">{{
"submit" | i18n
}}</bit-submit-button>
<button
type="submit"
buttonType="primary"
bitButton
[loading]="form.loading"
[disabled]="!formGroup.valid"
>
{{ "submit" | i18n }}
</button>
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
{{ "cancel" | i18n }}
</button>
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/app/settings/premium.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ <h1>{{ "goPremium" | i18n }}</h1>
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
}}</small>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
</form>
</ng-container>
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
Expand Down Expand Up @@ -118,7 +118,7 @@ <h2 class="spaced-header mb-4">{{ "paymentInformation" | i18n }}</h2>
</p>
</div>
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
</form>
10 changes: 8 additions & 2 deletions apps/web/src/app/settings/two-factor-setup.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,15 @@ <h2 class="mt-5 spaced-header">
</div>
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
</div>
<bit-submit-button [loading]="form.loading" *ngIf="isDeviceVerificationSectionEnabled">
<button
type="submit"
buttonType="primary"
bitButton
[loading]="form.loading"
*ngIf="isDeviceVerificationSectionEnabled"
>
{{ "save" | i18n }}
</bit-submit-button>
</button>
</div>
</div>
</form>
Expand Down
3 changes: 0 additions & 3 deletions apps/web/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
ButtonModule,
CalloutModule,
FormFieldModule,
SubmitButtonModule,
MenuModule,
IconModule,
} from "@bitwarden/components";
Expand Down Expand Up @@ -44,7 +43,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
SubmitButtonModule,
IconModule,
],
exports: [
Expand All @@ -63,7 +61,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
SubmitButtonModule,
IconModule,
],
providers: [DatePipe],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,13 @@ <h1>{{ "scim" | i18n }}</h1>
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
</bit-form-field>

<bit-submit-button buttonType="primary" [loading]="form.loading" [disabled]="form.loading">
<button
type="submit"
buttonType="primary"
bitButton
[loading]="form.loading"
[disabled]="form.loading"
>
{{ "save" | i18n }}
</bit-submit-button>
</button>
</form>
8 changes: 8 additions & 0 deletions libs/components/src/button/button.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<span class="tw-relative">
<span [ngClass]="{ 'tw-invisible': loading }">
<ng-content></ng-content>
</span>
<span class="tw-absolute tw-inset-0" [ngClass]="{ 'tw-invisible': !loading }">
<i class="bwi bwi-spinner bwi-lg bwi-spin tw-align-baseline" aria-hidden="true"></i>
</span>
</span>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe("Button", () => {
let fixture: ComponentFixture<TestApp>;
let testAppComponent: TestApp;
let buttonDebugElement: DebugElement;
let disabledButtonDebugElement: DebugElement;
let linkDebugElement: DebugElement;

beforeEach(waitForAsync(() => {
Expand All @@ -20,6 +21,7 @@ describe("Button", () => {
fixture = TestBed.createComponent(TestApp);
testAppComponent = fixture.debugElement.componentInstance;
buttonDebugElement = fixture.debugElement.query(By.css("button"));
disabledButtonDebugElement = fixture.debugElement.query(By.css("button#disabled"));
linkDebugElement = fixture.debugElement.query(By.css("a"));
}));

Expand Down Expand Up @@ -60,16 +62,67 @@ describe("Button", () => {
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
});

it("should not be disabled when loading and disabled are false", () => {
testAppComponent.loading = false;
testAppComponent.disabled = false;
fixture.detectChanges();

expect(buttonDebugElement.attributes["loading"]).toBeFalsy();
expect(linkDebugElement.attributes["loading"]).toBeFalsy();
expect(buttonDebugElement.nativeElement.disabled).toBeFalsy();
});

it("should be disabled when disabled is true", () => {
testAppComponent.disabled = true;
fixture.detectChanges();

expect(buttonDebugElement.nativeElement.disabled).toBeTruthy();
// Anchor tags cannot be disabled.
});

it("should be disabled when attribute disabled is true", () => {
expect(disabledButtonDebugElement.nativeElement.disabled).toBeTruthy();
});

it("should be disabled when loading is true", () => {
testAppComponent.loading = true;
fixture.detectChanges();

expect(buttonDebugElement.nativeElement.disabled).toBeTruthy();
});
});

@Component({
selector: "test-app",
template: `
<button type="button" bitButton [buttonType]="buttonType" [block]="block">Button</button>
<a href="#" bitButton [buttonType]="buttonType" [block]="block"> Link </a>
<button
type="button"
bitButton
[buttonType]="buttonType"
[block]="block"
[disabled]="disabled"
[loading]="loading"
>
Button
</button>
<a
href="#"
bitButton
[buttonType]="buttonType"
[block]="block"
[disabled]="disabled"
[loading]="loading"
>
Link
</a>
<button id="disabled" type="button" bitButton disabled>Button</button>
`,
})
class TestApp {
buttonType: string;
block: boolean;
disabled: boolean;
loading: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Input, HostBinding, Directive } from "@angular/core";
import { Input, HostBinding, Component } from "@angular/core";

export type ButtonTypes = "primary" | "secondary" | "danger";

Expand Down Expand Up @@ -38,10 +38,11 @@ const buttonStyles: Record<ButtonTypes, string[]> = {
],
};

@Directive({
@Component({
selector: "button[bitButton], a[bitButton]",
templateUrl: "button.component.html",
})
export class ButtonDirective {
export class ButtonComponent {
@HostBinding("class") get classList() {
return [
"tw-font-semibold",
Expand All @@ -65,6 +66,14 @@ export class ButtonDirective {
.concat(buttonStyles[this.buttonType ?? "secondary"]);
}

@HostBinding("attr.disabled")
get disabledAttr() {
const disabled = this.disabled != null && this.disabled !== false;
return disabled || this.loading ? true : null;
}

@Input() buttonType: ButtonTypes = null;
@Input() block?: boolean;
@Input() loading = false;
@Input() disabled = false;
}
6 changes: 3 additions & 3 deletions libs/components/src/button/button.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";

import { ButtonDirective } from "./button.directive";
import { ButtonComponent } from "./button.component";

@NgModule({
imports: [CommonModule],
exports: [ButtonDirective],
declarations: [ButtonDirective],
exports: [ButtonComponent],
declarations: [ButtonComponent],
})
export class ButtonModule {}
Loading

0 comments on commit cd7c9bf

Please sign in to comment.