From cd7c9bfd9f45754057671c21a53b5da8db0d40f7 Mon Sep 17 00:00:00 2001
From: Andreas Coroiu
Date: Tue, 27 Sep 2022 11:25:53 +0200
Subject: [PATCH] [EC-556] refactor cl button (#3537)
* [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 67c447d54ce0f08b99e2efc63b28cafac3411486)
* [EC-556] fix: replaced buttons should be primary
Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
---
.../register-form.component.html | 8 ++-
.../trial-initiation/billing.component.html | 4 +-
.../settings/account.component.html | 4 +-
...nroll-master-password-reset.component.html | 4 +-
.../pages/breach-report.component.html | 4 +-
.../exposed-passwords-report.component.html | 4 +-
.../app/settings/change-kdf.component.html | 4 +-
.../settings/change-password.component.html | 4 +-
.../emergency-access-add-edit.component.html | 10 +++-
.../organization-plans.component.html | 12 +++-
.../src/app/settings/premium.component.html | 8 +--
.../settings/two-factor-setup.component.html | 10 +++-
apps/web/src/app/shared/shared.module.ts | 3 -
.../organizations/manage/scim.component.html | 10 +++-
.../src/button/button.component.html | 8 +++
...ctive.spec.ts => button.component.spec.ts} | 57 ++++++++++++++++++-
...utton.directive.ts => button.component.ts} | 15 ++++-
libs/components/src/button/button.module.ts | 6 +-
libs/components/src/button/button.stories.ts | 57 ++++++++++++++-----
libs/components/src/button/index.ts | 2 +-
libs/components/src/index.ts | 1 -
libs/components/src/submit-button/index.ts | 1 -
.../submit-button.component.html | 16 ------
.../submit-button/submit-button.component.ts | 19 -------
.../src/submit-button/submit-button.module.ts | 13 -----
.../submit-button/submit-button.stories.ts | 45 ---------------
26 files changed, 181 insertions(+), 148 deletions(-)
create mode 100644 libs/components/src/button/button.component.html
rename libs/components/src/button/{button.directive.spec.ts => button.component.spec.ts} (65%)
rename libs/components/src/button/{button.directive.ts => button.component.ts} (82%)
delete mode 100644 libs/components/src/submit-button/index.ts
delete mode 100644 libs/components/src/submit-button/submit-button.component.html
delete mode 100644 libs/components/src/submit-button/submit-button.component.ts
delete mode 100644 libs/components/src/submit-button/submit-button.module.ts
delete mode 100644 libs/components/src/submit-button/submit-button.stories.ts
diff --git a/apps/web/src/app/accounts/register-form/register-form.component.html b/apps/web/src/app/accounts/register-form/register-form.component.html
index 56364086ff9..d9456d5a6e9 100644
--- a/apps/web/src/app/accounts/register-form/register-form.component.html
+++ b/apps/web/src/app/accounts/register-form/register-form.component.html
@@ -114,7 +114,9 @@
- {{ "createAccount" | i18n }}
+
- {{ "logIn" | i18n }}
+
diff --git a/apps/web/src/app/accounts/trial-initiation/billing.component.html b/apps/web/src/app/accounts/trial-initiation/billing.component.html
index 4486d0672dd..0eb203f72ca 100644
--- a/apps/web/src/app/accounts/trial-initiation/billing.component.html
+++ b/apps/web/src/app/accounts/trial-initiation/billing.component.html
@@ -40,7 +40,9 @@
- {{ "startTrial" | i18n }}
+
diff --git a/apps/web/src/app/organizations/settings/account.component.html b/apps/web/src/app/organizations/settings/account.component.html
index 73a2f7872e7..1f2e145ae7a 100644
--- a/apps/web/src/app/organizations/settings/account.component.html
+++ b/apps/web/src/app/organizations/settings/account.component.html
@@ -66,9 +66,9 @@
-
+
+
-
+
+
{{ "reportError" | i18n }}...
diff --git a/apps/web/src/app/reports/pages/exposed-passwords-report.component.html b/apps/web/src/app/reports/pages/exposed-passwords-report.component.html
index 2c5547efc7c..0fce002310b 100644
--- a/apps/web/src/app/reports/pages/exposed-passwords-report.component.html
+++ b/apps/web/src/app/reports/pages/exposed-passwords-report.component.html
@@ -2,9 +2,9 @@
{{ "exposedPasswordsReport" | i18n }}
{{ "exposedPasswordsReportDesc" | i18n }}
-
+
+
{{ "noExposedPasswords" | i18n }}
diff --git a/apps/web/src/app/settings/change-kdf.component.html b/apps/web/src/app/settings/change-kdf.component.html
index b06cf01d060..1b3b62a03fb 100644
--- a/apps/web/src/app/settings/change-kdf.component.html
+++ b/apps/web/src/app/settings/change-kdf.component.html
@@ -71,7 +71,7 @@
-
+
+
diff --git a/apps/web/src/app/settings/change-password.component.html b/apps/web/src/app/settings/change-password.component.html
index 6f36236a7ae..e74881db025 100644
--- a/apps/web/src/app/settings/change-password.component.html
+++ b/apps/web/src/app/settings/change-password.component.html
@@ -100,7 +100,7 @@
-
+
+
diff --git a/apps/web/src/app/settings/emergency-access-add-edit.component.html b/apps/web/src/app/settings/emergency-access-add-edit.component.html
index 410489321a1..b438cee937c 100644
--- a/apps/web/src/app/settings/emergency-access-add-edit.component.html
+++ b/apps/web/src/app/settings/emergency-access-add-edit.component.html
@@ -100,9 +100,15 @@
- {{
- "submit" | i18n
- }}
+
diff --git a/apps/web/src/app/settings/premium.component.html b/apps/web/src/app/settings/premium.component.html
index 63995b457ac..13266fd9ca5 100644
--- a/apps/web/src/app/settings/premium.component.html
+++ b/apps/web/src/app/settings/premium.component.html
@@ -68,9 +68,9 @@
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
}}
-
+
+
{{ "paymentChargedAnnually" | i18n }}
-
+
+
diff --git a/apps/web/src/app/settings/two-factor-setup.component.html b/apps/web/src/app/settings/two-factor-setup.component.html
index 698e7fd9c07..b846fdb9816 100644
--- a/apps/web/src/app/settings/two-factor-setup.component.html
+++ b/apps/web/src/app/settings/two-factor-setup.component.html
@@ -77,9 +77,15 @@
{{ "deviceVerificationDesc" | i18n }}
-
+
+
diff --git a/apps/web/src/app/shared/shared.module.ts b/apps/web/src/app/shared/shared.module.ts
index 342948bb515..c0a076e545e 100644
--- a/apps/web/src/app/shared/shared.module.ts
+++ b/apps/web/src/app/shared/shared.module.ts
@@ -12,7 +12,6 @@ import {
ButtonModule,
CalloutModule,
FormFieldModule,
- SubmitButtonModule,
MenuModule,
IconModule,
} from "@bitwarden/components";
@@ -44,7 +43,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
- SubmitButtonModule,
IconModule,
],
exports: [
@@ -63,7 +61,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
- SubmitButtonModule,
IconModule,
],
providers: [DatePipe],
diff --git a/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.html b/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.html
index 54fe44e073c..3d27448753f 100644
--- a/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.html
+++ b/bitwarden_license/bit-web/src/app/organizations/manage/scim.component.html
@@ -81,7 +81,13 @@
{{ "scimApiKeyHelperText" | i18n }}
-
+
+
diff --git a/libs/components/src/button/button.component.html b/libs/components/src/button/button.component.html
new file mode 100644
index 00000000000..4875c159e92
--- /dev/null
+++ b/libs/components/src/button/button.component.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/libs/components/src/button/button.directive.spec.ts b/libs/components/src/button/button.component.spec.ts
similarity index 65%
rename from libs/components/src/button/button.directive.spec.ts
rename to libs/components/src/button/button.component.spec.ts
index a7c3024e480..48aa8928e90 100644
--- a/libs/components/src/button/button.directive.spec.ts
+++ b/libs/components/src/button/button.component.spec.ts
@@ -8,6 +8,7 @@ describe("Button", () => {
let fixture: ComponentFixture;
let testAppComponent: TestApp;
let buttonDebugElement: DebugElement;
+ let disabledButtonDebugElement: DebugElement;
let linkDebugElement: DebugElement;
beforeEach(waitForAsync(() => {
@@ -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"));
}));
@@ -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: `
-
- Link
+
+
+ Link
+
+
+
`,
})
class TestApp {
buttonType: string;
block: boolean;
+ disabled: boolean;
+ loading: boolean;
}
diff --git a/libs/components/src/button/button.directive.ts b/libs/components/src/button/button.component.ts
similarity index 82%
rename from libs/components/src/button/button.directive.ts
rename to libs/components/src/button/button.component.ts
index 5c4b0039aef..eeba83b8156 100644
--- a/libs/components/src/button/button.directive.ts
+++ b/libs/components/src/button/button.component.ts
@@ -1,4 +1,4 @@
-import { Input, HostBinding, Directive } from "@angular/core";
+import { Input, HostBinding, Component } from "@angular/core";
export type ButtonTypes = "primary" | "secondary" | "danger";
@@ -38,10 +38,11 @@ const buttonStyles: Record = {
],
};
-@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",
@@ -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;
}
diff --git a/libs/components/src/button/button.module.ts b/libs/components/src/button/button.module.ts
index c9c3822abfa..448e7c9dcf6 100644
--- a/libs/components/src/button/button.module.ts
+++ b/libs/components/src/button/button.module.ts
@@ -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 {}
diff --git a/libs/components/src/button/button.stories.ts b/libs/components/src/button/button.stories.ts
index f09b8701b1b..4b9b88d48b1 100644
--- a/libs/components/src/button/button.stories.ts
+++ b/libs/components/src/button/button.stories.ts
@@ -1,12 +1,14 @@
import { Meta, Story } from "@storybook/angular";
-import { ButtonDirective } from "./button.directive";
+import { ButtonComponent } from "./button.component";
export default {
title: "Component Library/Button",
- component: ButtonDirective,
+ component: ButtonComponent,
args: {
buttonType: "primary",
+ disabled: false,
+ loading: false,
},
parameters: {
design: {
@@ -16,11 +18,11 @@ export default {
},
} as Meta;
-const Template: Story = (args: ButtonDirective) => ({
+const Template: Story = (args: ButtonComponent) => ({
props: args,
template: `
-
- Link
+
+ Link
`,
});
@@ -39,21 +41,50 @@ Danger.args = {
buttonType: "danger",
};
-const DisabledTemplate: Story = (args) => ({
+const AllStylesTemplate: Story = (args) => ({
props: args,
template: `
-
-
-
+
+
+
`,
});
-export const Disabled = DisabledTemplate.bind({});
-Disabled.args = {
- size: "small",
+export const Loading = AllStylesTemplate.bind({});
+Loading.args = {
+ disabled: false,
+ loading: true,
};
-const BlockTemplate: Story = (args: ButtonDirective) => ({
+export const Disabled = AllStylesTemplate.bind({});
+Disabled.args = {
+ disabled: true,
+ loading: false,
+};
+
+const DisabledWithAttributeTemplate: Story = (args) => ({
+ props: args,
+ template: `
+
+
+
+
+
+
+
+
+
+
+ `,
+});
+
+export const DisabledWithAttribute = DisabledWithAttributeTemplate.bind({});
+DisabledWithAttribute.args = {
+ disabled: true,
+ loading: false,
+};
+
+const BlockTemplate: Story = (args: ButtonComponent) => ({
props: args,
template: `
diff --git a/libs/components/src/button/index.ts b/libs/components/src/button/index.ts
index 1bdd62ddbcf..ff86120cb11 100644
--- a/libs/components/src/button/index.ts
+++ b/libs/components/src/button/index.ts
@@ -1,2 +1,2 @@
-export * from "./button.directive";
+export * from "./button.component";
export * from "./button.module";
diff --git a/libs/components/src/index.ts b/libs/components/src/index.ts
index 1f1ae6a8d2b..264c655d80f 100644
--- a/libs/components/src/index.ts
+++ b/libs/components/src/index.ts
@@ -7,7 +7,6 @@ export * from "./icon";
export * from "./icon-button";
export * from "./menu";
export * from "./dialog";
-export * from "./submit-button";
export * from "./link";
export * from "./tabs";
export * from "./toggle-group";
diff --git a/libs/components/src/submit-button/index.ts b/libs/components/src/submit-button/index.ts
deleted file mode 100644
index ae7d96d2c1a..00000000000
--- a/libs/components/src/submit-button/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./submit-button.module";
diff --git a/libs/components/src/submit-button/submit-button.component.html b/libs/components/src/submit-button/submit-button.component.html
deleted file mode 100644
index 9d9657ba7ee..00000000000
--- a/libs/components/src/submit-button/submit-button.component.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
diff --git a/libs/components/src/submit-button/submit-button.component.ts b/libs/components/src/submit-button/submit-button.component.ts
deleted file mode 100644
index 27408349da7..00000000000
--- a/libs/components/src/submit-button/submit-button.component.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Component, HostBinding, Input } from "@angular/core";
-
-import { ButtonTypes } from "../button";
-
-@Component({
- selector: "bit-submit-button",
- templateUrl: "./submit-button.component.html",
-})
-export class SubmitButtonComponent {
- @Input() buttonType: ButtonTypes = "primary";
- @Input() disabled = false;
- @Input() loading: boolean;
-
- @Input() block?: boolean;
-
- @HostBinding("class") get classList() {
- return this.block == null || this.block === false ? [] : ["tw-w-full", "tw-block"];
- }
-}
diff --git a/libs/components/src/submit-button/submit-button.module.ts b/libs/components/src/submit-button/submit-button.module.ts
deleted file mode 100644
index c7ab7567e64..00000000000
--- a/libs/components/src/submit-button/submit-button.module.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { CommonModule } from "@angular/common";
-import { NgModule } from "@angular/core";
-
-import { ButtonModule } from "../button";
-
-import { SubmitButtonComponent } from "./submit-button.component";
-
-@NgModule({
- imports: [CommonModule, ButtonModule],
- exports: [SubmitButtonComponent],
- declarations: [SubmitButtonComponent],
-})
-export class SubmitButtonModule {}
diff --git a/libs/components/src/submit-button/submit-button.stories.ts b/libs/components/src/submit-button/submit-button.stories.ts
deleted file mode 100644
index cf19b1c8e4b..00000000000
--- a/libs/components/src/submit-button/submit-button.stories.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Meta, moduleMetadata, Story } from "@storybook/angular";
-
-import { SubmitButtonComponent } from "./submit-button.component";
-import { SubmitButtonModule } from "./submit-button.module";
-
-export default {
- title: "Component Library/Submit Button",
- component: SubmitButtonComponent,
- decorators: [
- moduleMetadata({
- imports: [SubmitButtonModule],
- }),
- ],
- args: {
- buttonType: "primary",
- loading: false,
- block: false,
- },
- parameters: {
- design: {
- type: "figma",
- url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library?node-id=1881%3A16733",
- },
- },
-} as Meta;
-
-const Template: Story = (args: SubmitButtonComponent) => ({
- props: args,
- template: `
- Submit
- `,
-});
-
-export const Primary = Template.bind({});
-Primary.args = {};
-
-export const Loading = Template.bind({});
-Loading.args = {
- loading: true,
-};
-
-export const Disabled = Template.bind({});
-Disabled.args = {
- disabled: true,
-};