mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +00:00
[CL-95] loading spinner (#16363)
* add spiner from previous branch * add loading spinner to button * Add spinner to dialog * Add spinner to icon button * add spinner to multi select component * fix spinner positioning * Add mock i18n in stories where needed * round stroke caps. Update classes * fix ts error * fix broken tests * add missing translation keys to stories * Add mising key for layout * Add mising key for nav group * Add mising key for spotlight * Add mising key for product switcher * Add mising key for dialog service * add translation to copy click story
This commit is contained in:
@@ -124,6 +124,7 @@ export default {
|
||||
switchProducts: "Switch Products",
|
||||
secureYourInfrastructure: "Secure your infrastructure",
|
||||
protectYourFamilyOrBusiness: "Protect your family or business",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@ const meta: Meta<SpotlightComponent> = {
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
close: "Close",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -148,6 +148,7 @@ export default {
|
||||
required: "required",
|
||||
inputRequired: "Input is required.",
|
||||
inputEmail: "Input is not an email-address.",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,11 +3,13 @@ import { action } from "@storybook/addon-actions";
|
||||
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
|
||||
import { delay, of } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
|
||||
import { ButtonModule } from "../button";
|
||||
import { IconButtonModule } from "../icon-button";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { AsyncActionsModule } from "./async-actions.module";
|
||||
import { BitActionDirective } from "./bit-action.directive";
|
||||
@@ -103,6 +105,14 @@ export default {
|
||||
error: action("LogService.error"),
|
||||
} as Partial<LogService>,
|
||||
},
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
||||
@@ -19,6 +19,7 @@ describe("BannerComponent", () => {
|
||||
useFactory: () =>
|
||||
new I18nMockService({
|
||||
close: "Close",
|
||||
loading: "Loading",
|
||||
}),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -22,6 +22,7 @@ export default {
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
close: "Close",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -35,6 +35,7 @@ export default {
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
moreBreadcrumbs: "More breadcrumbs",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
<span [ngClass]="{ 'tw-invisible': showLoadingStyle() }">
|
||||
<ng-content></ng-content>
|
||||
</span>
|
||||
<span
|
||||
class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center"
|
||||
[ngClass]="{ 'tw-invisible': !showLoadingStyle() }"
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-lg bwi-spin" aria-hidden="true"></i>
|
||||
</span>
|
||||
@if (showLoadingStyle()) {
|
||||
<span class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center">
|
||||
<bit-spinner size="fill" noColor></bit-spinner>
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { debounce, interval } from "rxjs";
|
||||
|
||||
import { AriaDisableDirective } from "../a11y";
|
||||
import { ButtonLikeAbstraction, ButtonType, ButtonSize } from "../shared/button-like.abstraction";
|
||||
import { SpinnerComponent } from "../spinner";
|
||||
import { ariaDisableElement } from "../utils";
|
||||
|
||||
const focusRing = [
|
||||
@@ -60,7 +61,7 @@ const buttonStyles: Record<ButtonType, string[]> = {
|
||||
selector: "button[bitButton], a[bitButton]",
|
||||
templateUrl: "button.component.html",
|
||||
providers: [{ provide: ButtonLikeAbstraction, useExisting: ButtonComponent }],
|
||||
imports: [NgClass],
|
||||
imports: [NgClass, SpinnerComponent],
|
||||
hostDirectives: [AriaDisableDirective],
|
||||
})
|
||||
export class ButtonComponent implements ButtonLikeAbstraction {
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
import { Meta, StoryObj } from "@storybook/angular";
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { formatArgsForCodeSnippet } from "../../../../.storybook/format-args-for-code-snippet";
|
||||
import { I18nMockService } from "../utils/i18n-mock.service";
|
||||
|
||||
import { ButtonComponent } from "./button.component";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Button",
|
||||
component: ButtonComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () =>
|
||||
new I18nMockService({
|
||||
loading: "Loading",
|
||||
}),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
args: {
|
||||
disabled: false,
|
||||
loading: false,
|
||||
|
||||
@@ -38,6 +38,7 @@ export default {
|
||||
success: "Success",
|
||||
close: "Close",
|
||||
info: "Info",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -155,6 +155,7 @@ export default {
|
||||
toggleSideNavigation: "Toggle side navigation",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
>
|
||||
@if (loading()) {
|
||||
<div class="tw-absolute tw-flex tw-size-full tw-items-center tw-justify-center">
|
||||
<i class="bwi bwi-spinner bwi-spin bwi-lg" [attr.aria-label]="'loading' | i18n"></i>
|
||||
<bit-spinner></bit-spinner>
|
||||
</div>
|
||||
}
|
||||
<div
|
||||
|
||||
@@ -17,6 +17,7 @@ import { combineLatest, switchMap } from "rxjs";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
import { BitIconButtonComponent } from "../../icon-button/icon-button.component";
|
||||
import { SpinnerComponent } from "../../spinner";
|
||||
import { TypographyDirective } from "../../typography/typography.directive";
|
||||
import { hasScrollableContent$ } from "../../utils/";
|
||||
import { hasScrolledFrom } from "../../utils/has-scrolled-from";
|
||||
@@ -41,6 +42,7 @@ import { DialogTitleContainerDirective } from "../directives/dialog-title-contai
|
||||
I18nPipe,
|
||||
CdkTrapFocus,
|
||||
CdkScrollable,
|
||||
SpinnerComponent,
|
||||
],
|
||||
})
|
||||
export class DialogComponent {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { ButtonModule } from "../../button";
|
||||
import { I18nMockService } from "../../utils";
|
||||
import { DialogModule } from "../dialog.module";
|
||||
|
||||
import { SimpleDialogComponent } from "./simple-dialog.component";
|
||||
@@ -12,6 +15,16 @@ export default {
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [ButtonModule, NoopAnimationsModule, DialogModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
parameters: {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { IconButtonModule } from "../icon-button";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { DisclosureTriggerForDirective } from "./disclosure-trigger-for.directive";
|
||||
import { DisclosureComponent } from "./disclosure.component";
|
||||
@@ -11,6 +14,16 @@ export default {
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [DisclosureTriggerForDirective, DisclosureComponent, IconButtonModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
parameters: {
|
||||
|
||||
@@ -41,6 +41,7 @@ export default {
|
||||
return new I18nMockService({
|
||||
...mockLayoutI18n,
|
||||
close: "Close",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -63,6 +63,7 @@ export default {
|
||||
inputRequired: "Input is required.",
|
||||
inputEmail: "Input is not an email-address.",
|
||||
toggleVisibility: "Toggle visibility",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -48,6 +48,7 @@ describe("PasswordInputToggle", () => {
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({
|
||||
toggleVisibility: "Toggle visibility",
|
||||
loading: "Loading",
|
||||
}),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -19,7 +19,10 @@ export default {
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({ toggleVisibility: "Toggle visibility" }),
|
||||
useValue: new I18nMockService({
|
||||
toggleVisibility: "Toggle visibility",
|
||||
loading: "Loading",
|
||||
}),
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center"
|
||||
[ngClass]="{ 'tw-invisible': !showLoadingStyle() }"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-lg': size() === 'default' }"
|
||||
></i>
|
||||
<bit-spinner size="fill" noColor></bit-spinner>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { AriaDisableDirective } from "../a11y";
|
||||
import { setA11yTitleAndAriaLabel } from "../a11y/set-a11y-title-and-aria-label";
|
||||
import { ButtonLikeAbstraction } from "../shared/button-like.abstraction";
|
||||
import { FocusableElement } from "../shared/focusable-element";
|
||||
import { SpinnerComponent } from "../spinner";
|
||||
import { ariaDisableElement } from "../utils";
|
||||
|
||||
export type IconButtonType = "primary" | "danger" | "contrast" | "main" | "muted" | "nav-contrast";
|
||||
@@ -87,7 +88,7 @@ const sizes: Record<IconButtonSize, string[]> = {
|
||||
{ provide: ButtonLikeAbstraction, useExisting: BitIconButtonComponent },
|
||||
{ provide: FocusableElement, useExisting: BitIconButtonComponent },
|
||||
],
|
||||
imports: [NgClass],
|
||||
imports: [NgClass, SpinnerComponent],
|
||||
host: {
|
||||
/**
|
||||
* When the `bitIconButton` input is dynamic from a consumer, Angular doesn't put the
|
||||
|
||||
@@ -1,12 +1,29 @@
|
||||
import { Meta, StoryObj } from "@storybook/angular";
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { formatArgsForCodeSnippet } from "../../../../.storybook/format-args-for-code-snippet";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { BitIconButtonComponent } from "./icon-button.component";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Icon Button",
|
||||
component: BitIconButtonComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
args: {
|
||||
bitIconButton: "bwi-plus",
|
||||
label: "Your button label here",
|
||||
|
||||
@@ -44,6 +44,7 @@ export default {
|
||||
skipToContent: "Skip to content",
|
||||
submenu: "submenu",
|
||||
toggleCollapse: "toggle collapse",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,4 +4,5 @@ export const mockLayoutI18n = {
|
||||
skipToContent: "Skip to content",
|
||||
submenu: "submenu",
|
||||
toggleCollapse: "toggle collapse",
|
||||
loading: "Loading",
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { OverlayModule } from "@angular/cdk/overlay";
|
||||
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { ButtonModule } from "../button/button.module";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
|
||||
import { MenuModule } from "./menu.module";
|
||||
@@ -12,6 +15,12 @@ export default {
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [MenuModule, OverlayModule, ButtonModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({ loading: "Loading" }),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
parameters: {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
appendTo="body"
|
||||
>
|
||||
<ng-template ng-loadingspinner-tmp>
|
||||
<i class="bwi bwi-spinner bwi-spin tw-me-1" [title]="loadingText" aria-hidden="true"></i>
|
||||
<bit-spinner></bit-spinner>
|
||||
</ng-template>
|
||||
<ng-template ng-label-tmp let-item="item" let-clear="clear">
|
||||
<button
|
||||
|
||||
@@ -27,6 +27,7 @@ import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
import { BadgeModule } from "../badge";
|
||||
import { BitFormFieldControl } from "../form-field/form-field-control";
|
||||
import { SpinnerComponent } from "../spinner";
|
||||
|
||||
import { SelectItemView } from "./models/select-item-view";
|
||||
|
||||
@@ -37,7 +38,14 @@ let nextId = 0;
|
||||
selector: "bit-multi-select",
|
||||
templateUrl: "./multi-select.component.html",
|
||||
providers: [{ provide: BitFormFieldControl, useExisting: MultiSelectComponent }],
|
||||
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, BadgeModule, I18nPipe],
|
||||
imports: [
|
||||
NgSelectModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
BadgeModule,
|
||||
I18nPipe,
|
||||
SpinnerComponent,
|
||||
],
|
||||
host: {
|
||||
"[id]": "this.id()",
|
||||
},
|
||||
|
||||
@@ -39,6 +39,7 @@ export default {
|
||||
toggleCollapse: "toggle collapse",
|
||||
toggleSideNavigation: "Toggle side navigation",
|
||||
skipToContent: "Skip to content",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -30,6 +30,7 @@ export default {
|
||||
toggleCollapse: "toggle collapse",
|
||||
toggleSideNavigation: "Toggle side navigation",
|
||||
skipToContent: "Skip to content",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -15,8 +15,10 @@ import {
|
||||
Security,
|
||||
VaultOpen,
|
||||
} from "@bitwarden/assets/svg";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { ButtonModule } from "../button";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { NoItemsComponent } from "./no-items.component";
|
||||
import { NoItemsModule } from "./no-items.module";
|
||||
@@ -27,6 +29,12 @@ export default {
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [ButtonModule, NoItemsModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({ loading: "Loading" }),
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
parameters: {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { Meta, StoryObj, componentWrapperDecorator, moduleMetadata } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { CardComponent } from "../card";
|
||||
import { IconButtonModule } from "../icon-button";
|
||||
import { ItemModule } from "../item";
|
||||
import { TypographyModule } from "../typography";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { SectionComponent, SectionHeaderComponent } from "./";
|
||||
|
||||
@@ -19,6 +22,12 @@ export default {
|
||||
IconButtonModule,
|
||||
ItemModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({ loading: "Loading" }),
|
||||
},
|
||||
],
|
||||
}),
|
||||
componentWrapperDecorator((story) => `<div class="tw-text-main">${story}</div>`),
|
||||
],
|
||||
|
||||
1
libs/components/src/spinner/index.ts
Normal file
1
libs/components/src/spinner/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./spinner.component";
|
||||
27
libs/components/src/spinner/spinner.component.html
Normal file
27
libs/components/src/spinner/spinner.component.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 56 56"
|
||||
fill="none"
|
||||
class="tw-size-full tw-animate-spin"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle
|
||||
cx="28"
|
||||
cy="28"
|
||||
r="23"
|
||||
class="tw-stroke-primary-600"
|
||||
pathLength="4"
|
||||
stroke-width="5"
|
||||
stroke-dasharray="1 3"
|
||||
stroke-linecap="round"
|
||||
></circle>
|
||||
<circle
|
||||
cx="28"
|
||||
cy="28"
|
||||
r="23"
|
||||
class="tw-stroke-primary-600"
|
||||
stroke-width="5"
|
||||
opacity="0.4"
|
||||
></circle>
|
||||
</svg>
|
||||
<span class="tw-sr-only" *ngIf="sr">{{ title }}</span>
|
||||
|
After Width: | Height: | Size: 519 B |
51
libs/components/src/spinner/spinner.component.ts
Normal file
51
libs/components/src/spinner/spinner.component.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, HostBinding, Input, booleanAttribute } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
@Component({
|
||||
selector: "bit-spinner",
|
||||
templateUrl: "spinner.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
})
|
||||
export class SpinnerComponent {
|
||||
/**
|
||||
* The size of the spinner. Defaults to `large`.
|
||||
*/
|
||||
@Input() size: "fill" | "small" | "large" = "large";
|
||||
|
||||
/**
|
||||
* Disable the default color of the spinner, inherits the text color.
|
||||
*/
|
||||
@Input({ transform: booleanAttribute }) noColor = false;
|
||||
|
||||
/**
|
||||
* Accessibility title. Defaults to `Loading`.
|
||||
*/
|
||||
@Input() title = this.i18nService.t("loading");
|
||||
|
||||
/**
|
||||
* Display text for screen readers.
|
||||
*/
|
||||
@Input({ transform: booleanAttribute }) sr = true;
|
||||
|
||||
@HostBinding("class") get classList() {
|
||||
return ["tw-inline-block", "tw-overflow-hidden", "tw-flex", "tw-items-center"]
|
||||
.concat(this.sizeClass)
|
||||
.concat([this.noColor ? "" : "tw-text-primary-600"]);
|
||||
}
|
||||
|
||||
constructor(private i18nService: I18nService) {}
|
||||
|
||||
get sizeClass() {
|
||||
switch (this.size) {
|
||||
case "small":
|
||||
return ["tw-h-4"];
|
||||
case "large":
|
||||
return ["tw-h-16"];
|
||||
default:
|
||||
return ["tw-h-full", "tw-w-full"];
|
||||
}
|
||||
}
|
||||
}
|
||||
53
libs/components/src/spinner/spinner.stories.ts
Normal file
53
libs/components/src/spinner/spinner.stories.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { SpinnerComponent } from "./spinner.component";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Spinner",
|
||||
component: SpinnerComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [CommonModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
declarations: [],
|
||||
}),
|
||||
],
|
||||
parameters: {
|
||||
design: {
|
||||
type: "figma",
|
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library?node-id=1881%3A16956",
|
||||
},
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
type Story = StoryObj<SpinnerComponent>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Fill: Story = {
|
||||
args: {
|
||||
size: "fill",
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
args: {
|
||||
size: "small",
|
||||
},
|
||||
};
|
||||
@@ -23,6 +23,7 @@ import { KitchenSinkSharedModule } from "../kitchen-sink-shared.module";
|
||||
inputMaxValue: (max) => `Input value must not exceed ${max}.`,
|
||||
inputMinValue: (min) => `Input value must be at least ${min}.`,
|
||||
inputRequired: "Input is required.",
|
||||
loading: "Loading",
|
||||
multiSelectClearAll: "Clear all",
|
||||
multiSelectLoading: "Retrieving options...",
|
||||
multiSelectNotFound: "No items found",
|
||||
|
||||
@@ -64,6 +64,7 @@ export default {
|
||||
toggleSideNavigation: "Toggle side navigation",
|
||||
yes: "Yes",
|
||||
no: "No",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,8 +3,11 @@ import { Component, importProvidersFrom } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { applicationConfig, Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { ButtonModule } from "../button";
|
||||
import { FormFieldModule } from "../form-field";
|
||||
import { I18nMockService } from "../utils";
|
||||
|
||||
import { TabGroupComponent } from "./tab-group/tab-group.component";
|
||||
import { TabsModule } from "./tabs.module";
|
||||
@@ -56,6 +59,12 @@ export default {
|
||||
ItemWithChildCounterDummyComponent,
|
||||
DisabledDummyComponent,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: new I18nMockService({ loading: "Loading" }),
|
||||
},
|
||||
],
|
||||
}),
|
||||
applicationConfig({
|
||||
providers: [
|
||||
|
||||
@@ -55,6 +55,7 @@ export default {
|
||||
error: "Error",
|
||||
warning: "Warning",
|
||||
info: "Info",
|
||||
loading: "Loading",
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user