mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[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 67c447d54c
)
* [EC-556] fix: replaced buttons should be primary
Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
This commit is contained in:
parent
b5de573497
commit
cd7c9bfd9f
@ -114,7 +114,9 @@
|
|||||||
|
|
||||||
<div class="tw-mb-3 tw-flex">
|
<div class="tw-mb-3 tw-flex">
|
||||||
<ng-container *ngIf="!accountCreated">
|
<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
|
<a
|
||||||
bitButton
|
bitButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
@ -126,7 +128,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="accountCreated">
|
<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>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
|
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
|
||||||
|
@ -40,7 +40,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tw-flex tw-space-x-2">
|
<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>
|
<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,9 +66,9 @@
|
|||||||
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
|
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<ng-container *ngIf="canUseApi">
|
<ng-container *ngIf="canUseApi">
|
||||||
<div class="secondary-header border-0 mb-0">
|
<div class="secondary-header border-0 mb-0">
|
||||||
|
@ -32,9 +32,9 @@
|
|||||||
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
|
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<button
|
<button
|
||||||
bitButton
|
bitButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
|
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "checkBreaches" | i18n }}
|
{{ "checkBreaches" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
|
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
|
||||||
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
|
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
|
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
|
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
|
||||||
<bit-submit-button [loading]="loading" (click)="load()">
|
<button type="submit" buttonType="primary" bitButton [loading]="loading" (click)="load()">
|
||||||
{{ "checkExposedPasswords" | i18n }}
|
{{ "checkExposedPasswords" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<div class="mt-4" *ngIf="hasLoaded">
|
<div class="mt-4" *ngIf="hasLoaded">
|
||||||
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
|
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
|
||||||
{{ "noExposedPasswords" | i18n }}
|
{{ "noExposedPasswords" | i18n }}
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "changeKdf" | i18n }}
|
{{ "changeKdf" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "changeMasterPassword" | i18n }}
|
{{ "changeMasterPassword" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -100,9 +100,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<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 }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
|
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
|
||||||
{{ "cancel" | i18n }}
|
{{ "cancel" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -318,9 +318,15 @@
|
|||||||
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
|
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<bit-submit-button [loading]="form.loading" [disabled]="!formGroup.valid">{{
|
<button
|
||||||
"submit" | i18n
|
type="submit"
|
||||||
}}</bit-submit-button>
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="form.loading"
|
||||||
|
[disabled]="!formGroup.valid"
|
||||||
|
>
|
||||||
|
{{ "submit" | i18n }}
|
||||||
|
</button>
|
||||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
||||||
{{ "cancel" | i18n }}
|
{{ "cancel" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -68,9 +68,9 @@
|
|||||||
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
|
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" buttonType="primary" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
|
||||||
@ -118,7 +118,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
|
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
|
||||||
<bit-submit-button [loading]="form.loading">
|
<button type="submit" bitButton [loading]="form.loading">
|
||||||
{{ "submit" | i18n }}
|
{{ "submit" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -77,9 +77,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
|
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
|
||||||
</div>
|
</div>
|
||||||
<bit-submit-button [loading]="form.loading" *ngIf="isDeviceVerificationSectionEnabled">
|
<button
|
||||||
|
type="submit"
|
||||||
|
buttonType="primary"
|
||||||
|
bitButton
|
||||||
|
[loading]="form.loading"
|
||||||
|
*ngIf="isDeviceVerificationSectionEnabled"
|
||||||
|
>
|
||||||
{{ "save" | i18n }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
CalloutModule,
|
CalloutModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
MenuModule,
|
MenuModule,
|
||||||
IconModule,
|
IconModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
@ -44,7 +43,6 @@ import "./locales";
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
MenuModule,
|
MenuModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
IconModule,
|
IconModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
@ -63,7 +61,6 @@ import "./locales";
|
|||||||
ButtonModule,
|
ButtonModule,
|
||||||
MenuModule,
|
MenuModule,
|
||||||
FormFieldModule,
|
FormFieldModule,
|
||||||
SubmitButtonModule,
|
|
||||||
IconModule,
|
IconModule,
|
||||||
],
|
],
|
||||||
providers: [DatePipe],
|
providers: [DatePipe],
|
||||||
|
@ -81,7 +81,13 @@
|
|||||||
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
|
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
|
||||||
</bit-form-field>
|
</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 }}
|
{{ "save" | i18n }}
|
||||||
</bit-submit-button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
8
libs/components/src/button/button.component.html
Normal file
8
libs/components/src/button/button.component.html
Normal file
@ -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>
|
@ -8,6 +8,7 @@ describe("Button", () => {
|
|||||||
let fixture: ComponentFixture<TestApp>;
|
let fixture: ComponentFixture<TestApp>;
|
||||||
let testAppComponent: TestApp;
|
let testAppComponent: TestApp;
|
||||||
let buttonDebugElement: DebugElement;
|
let buttonDebugElement: DebugElement;
|
||||||
|
let disabledButtonDebugElement: DebugElement;
|
||||||
let linkDebugElement: DebugElement;
|
let linkDebugElement: DebugElement;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(waitForAsync(() => {
|
||||||
@ -20,6 +21,7 @@ describe("Button", () => {
|
|||||||
fixture = TestBed.createComponent(TestApp);
|
fixture = TestBed.createComponent(TestApp);
|
||||||
testAppComponent = fixture.debugElement.componentInstance;
|
testAppComponent = fixture.debugElement.componentInstance;
|
||||||
buttonDebugElement = fixture.debugElement.query(By.css("button"));
|
buttonDebugElement = fixture.debugElement.query(By.css("button"));
|
||||||
|
disabledButtonDebugElement = fixture.debugElement.query(By.css("button#disabled"));
|
||||||
linkDebugElement = fixture.debugElement.query(By.css("a"));
|
linkDebugElement = fixture.debugElement.query(By.css("a"));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -60,16 +62,67 @@ describe("Button", () => {
|
|||||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
|
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
|
||||||
expect(linkDebugElement.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({
|
@Component({
|
||||||
selector: "test-app",
|
selector: "test-app",
|
||||||
template: `
|
template: `
|
||||||
<button type="button" bitButton [buttonType]="buttonType" [block]="block">Button</button>
|
<button
|
||||||
<a href="#" bitButton [buttonType]="buttonType" [block]="block"> Link </a>
|
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 {
|
class TestApp {
|
||||||
buttonType: string;
|
buttonType: string;
|
||||||
block: boolean;
|
block: boolean;
|
||||||
|
disabled: boolean;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { Input, HostBinding, Directive } from "@angular/core";
|
import { Input, HostBinding, Component } from "@angular/core";
|
||||||
|
|
||||||
export type ButtonTypes = "primary" | "secondary" | "danger";
|
export type ButtonTypes = "primary" | "secondary" | "danger";
|
||||||
|
|
||||||
@ -38,10 +38,11 @@ const buttonStyles: Record<ButtonTypes, string[]> = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@Directive({
|
@Component({
|
||||||
selector: "button[bitButton], a[bitButton]",
|
selector: "button[bitButton], a[bitButton]",
|
||||||
|
templateUrl: "button.component.html",
|
||||||
})
|
})
|
||||||
export class ButtonDirective {
|
export class ButtonComponent {
|
||||||
@HostBinding("class") get classList() {
|
@HostBinding("class") get classList() {
|
||||||
return [
|
return [
|
||||||
"tw-font-semibold",
|
"tw-font-semibold",
|
||||||
@ -65,6 +66,14 @@ export class ButtonDirective {
|
|||||||
.concat(buttonStyles[this.buttonType ?? "secondary"]);
|
.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() buttonType: ButtonTypes = null;
|
||||||
@Input() block?: boolean;
|
@Input() block?: boolean;
|
||||||
|
@Input() loading = false;
|
||||||
|
@Input() disabled = false;
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
import { CommonModule } from "@angular/common";
|
||||||
import { NgModule } from "@angular/core";
|
import { NgModule } from "@angular/core";
|
||||||
|
|
||||||
import { ButtonDirective } from "./button.directive";
|
import { ButtonComponent } from "./button.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule],
|
imports: [CommonModule],
|
||||||
exports: [ButtonDirective],
|
exports: [ButtonComponent],
|
||||||
declarations: [ButtonDirective],
|
declarations: [ButtonComponent],
|
||||||
})
|
})
|
||||||
export class ButtonModule {}
|
export class ButtonModule {}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { Meta, Story } from "@storybook/angular";
|
import { Meta, Story } from "@storybook/angular";
|
||||||
|
|
||||||
import { ButtonDirective } from "./button.directive";
|
import { ButtonComponent } from "./button.component";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Component Library/Button",
|
title: "Component Library/Button",
|
||||||
component: ButtonDirective,
|
component: ButtonComponent,
|
||||||
args: {
|
args: {
|
||||||
buttonType: "primary",
|
buttonType: "primary",
|
||||||
|
disabled: false,
|
||||||
|
loading: false,
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
design: {
|
design: {
|
||||||
@ -16,11 +18,11 @@ export default {
|
|||||||
},
|
},
|
||||||
} as Meta;
|
} as Meta;
|
||||||
|
|
||||||
const Template: Story<ButtonDirective> = (args: ButtonDirective) => ({
|
const Template: Story<ButtonComponent> = (args: ButtonComponent) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: `
|
template: `
|
||||||
<button bitButton [buttonType]="buttonType" [block]="block">Button</button>
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block">Button</button>
|
||||||
<a bitButton [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">Link</a>
|
<a bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">Link</a>
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,21 +41,50 @@ Danger.args = {
|
|||||||
buttonType: "danger",
|
buttonType: "danger",
|
||||||
};
|
};
|
||||||
|
|
||||||
const DisabledTemplate: Story = (args) => ({
|
const AllStylesTemplate: Story = (args) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: `
|
template: `
|
||||||
<button bitButton disabled buttonType="primary" class="tw-mr-2">Primary</button>
|
<button bitButton [disabled]="disabled" [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||||
<button bitButton disabled buttonType="secondary" class="tw-mr-2">Secondary</button>
|
<button bitButton [disabled]="disabled" [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||||
<button bitButton disabled buttonType="danger" class="tw-mr-2">Danger</button>
|
<button bitButton [disabled]="disabled" [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Disabled = DisabledTemplate.bind({});
|
export const Loading = AllStylesTemplate.bind({});
|
||||||
Disabled.args = {
|
Loading.args = {
|
||||||
size: "small",
|
disabled: false,
|
||||||
|
loading: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const BlockTemplate: Story<ButtonDirective> = (args: ButtonDirective) => ({
|
export const Disabled = AllStylesTemplate.bind({});
|
||||||
|
Disabled.args = {
|
||||||
|
disabled: true,
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DisabledWithAttributeTemplate: Story = (args) => ({
|
||||||
|
props: args,
|
||||||
|
template: `
|
||||||
|
<ng-container *ngIf="disabled">
|
||||||
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||||
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||||
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="!disabled">
|
||||||
|
<button bitButton [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||||
|
<button bitButton [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||||
|
<button bitButton [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||||
|
</ng-container>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const DisabledWithAttribute = DisabledWithAttributeTemplate.bind({});
|
||||||
|
DisabledWithAttribute.args = {
|
||||||
|
disabled: true,
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const BlockTemplate: Story<ButtonComponent> = (args: ButtonComponent) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: `
|
template: `
|
||||||
<span class="tw-flex">
|
<span class="tw-flex">
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
export * from "./button.directive";
|
export * from "./button.component";
|
||||||
export * from "./button.module";
|
export * from "./button.module";
|
||||||
|
@ -7,7 +7,6 @@ export * from "./icon";
|
|||||||
export * from "./icon-button";
|
export * from "./icon-button";
|
||||||
export * from "./menu";
|
export * from "./menu";
|
||||||
export * from "./dialog";
|
export * from "./dialog";
|
||||||
export * from "./submit-button";
|
|
||||||
export * from "./link";
|
export * from "./link";
|
||||||
export * from "./tabs";
|
export * from "./tabs";
|
||||||
export * from "./toggle-group";
|
export * from "./toggle-group";
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from "./submit-button.module";
|
|
@ -1,16 +0,0 @@
|
|||||||
<button
|
|
||||||
bitButton
|
|
||||||
type="submit"
|
|
||||||
[block]="block"
|
|
||||||
[buttonType]="buttonType"
|
|
||||||
[disabled]="loading || disabled"
|
|
||||||
>
|
|
||||||
<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>
|
|
||||||
</button>
|
|
@ -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"];
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 {}
|
|
@ -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<SubmitButtonComponent> = (args: SubmitButtonComponent) => ({
|
|
||||||
props: args,
|
|
||||||
template: `<bit-submit-button [buttonType]="buttonType" [loading]="loading" [disabled]="disabled" [block]="block">
|
|
||||||
Submit
|
|
||||||
</bit-submit-button>`,
|
|
||||||
});
|
|
||||||
|
|
||||||
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,
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user