1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 08:13:42 +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:
Bryan Cunningham
2025-09-23 15:36:18 -04:00
committed by GitHub
parent 7865bb5e12
commit 9d82fc7dfc
40 changed files with 283 additions and 19 deletions

View File

@@ -0,0 +1 @@
export * from "./spinner.component";

View 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

View 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"];
}
}
}

View 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",
},
};