[CL-285] Add default loading state to popup-page (#10040)

This commit is contained in:
Victoria League 2024-07-15 14:29:58 -04:00 committed by GitHub
parent bc7c6dd04e
commit 154f15fa58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 31 deletions

View File

@ -3628,5 +3628,8 @@
}, },
"addAccount": { "addAccount": {
"message": "Add account" "message": "Add account"
},
"loading": {
"message": "Loading"
} }
} }

View File

@ -44,6 +44,14 @@ page looks nice when the extension is popped out.
- default - default
- Whatever content you want in `main`. - Whatever content you want in `main`.
**Inputs**
- `loading`
- When `true`, displays a loading state overlay instead of the default content. Defaults to
`false`.
- `loadingText`
- Custom text to be applied to the loading element for screenreaders only. Defaults to "Loading".
Basic usage example: Basic usage example:
```html ```html
@ -137,8 +145,20 @@ When the browser extension is popped out, the "popout" button should not be pass
<Story of={stories.PoppedOut} /> <Story of={stories.PoppedOut} />
</Canvas> </Canvas>
# Other stories
## Centered Content ## Centered Content
An example of how to center the default content.
<Canvas> <Canvas>
<Story of={stories.CenteredContent} /> <Story of={stories.CenteredContent} />
</Canvas> </Canvas>
## Loading
An example of what the loading state looks like.
<Canvas>
<Story of={stories.Loading} />
</Canvas>

View File

@ -62,27 +62,6 @@ class VaultComponent {
protected data = Array.from(Array(20).keys()); protected data = Array.from(Array(20).keys());
} }
@Component({
selector: "generator-placeholder",
template: ` <div class="tw-text-main">generator stuff here</div> `,
standalone: true,
})
class GeneratorComponent {}
@Component({
selector: "send-placeholder",
template: ` <div class="tw-text-main">send some stuff</div> `,
standalone: true,
})
class SendComponent {}
@Component({
selector: "settings-placeholder",
template: ` <div class="tw-text-main">change your settings</div> `,
standalone: true,
})
class SettingsComponent {}
@Component({ @Component({
selector: "mock-add-button", selector: "mock-add-button",
template: ` template: `
@ -186,7 +165,7 @@ class MockVaultPagePoppedComponent {}
<mock-current-account></mock-current-account> <mock-current-account></mock-current-account>
</ng-container> </ng-container>
</popup-header> </popup-header>
<generator-placeholder></generator-placeholder> <div class="tw-text-main">Generator content here</div>
</popup-page> </popup-page>
`, `,
standalone: true, standalone: true,
@ -196,7 +175,6 @@ class MockVaultPagePoppedComponent {}
MockAddButtonComponent, MockAddButtonComponent,
MockPopoutButtonComponent, MockPopoutButtonComponent,
MockCurrentAccountComponent, MockCurrentAccountComponent,
GeneratorComponent,
], ],
}) })
class MockGeneratorPageComponent {} class MockGeneratorPageComponent {}
@ -212,7 +190,7 @@ class MockGeneratorPageComponent {}
<mock-current-account></mock-current-account> <mock-current-account></mock-current-account>
</ng-container> </ng-container>
</popup-header> </popup-header>
<send-placeholder></send-placeholder> <div class="tw-text-main">Send content here</div>
</popup-page> </popup-page>
`, `,
standalone: true, standalone: true,
@ -222,7 +200,6 @@ class MockGeneratorPageComponent {}
MockAddButtonComponent, MockAddButtonComponent,
MockPopoutButtonComponent, MockPopoutButtonComponent,
MockCurrentAccountComponent, MockCurrentAccountComponent,
SendComponent,
], ],
}) })
class MockSendPageComponent {} class MockSendPageComponent {}
@ -238,7 +215,7 @@ class MockSendPageComponent {}
<mock-current-account></mock-current-account> <mock-current-account></mock-current-account>
</ng-container> </ng-container>
</popup-header> </popup-header>
<settings-placeholder></settings-placeholder> <div class="tw-text-main">Settings content here</div>
</popup-page> </popup-page>
`, `,
standalone: true, standalone: true,
@ -248,7 +225,6 @@ class MockSendPageComponent {}
MockAddButtonComponent, MockAddButtonComponent,
MockPopoutButtonComponent, MockPopoutButtonComponent,
MockCurrentAccountComponent, MockCurrentAccountComponent,
SettingsComponent,
], ],
}) })
class MockSettingsPageComponent {} class MockSettingsPageComponent {}
@ -312,6 +288,7 @@ export default {
useFactory: () => { useFactory: () => {
return new I18nMockService({ return new I18nMockService({
back: "Back", back: "Back",
loading: "Loading",
}); });
}, },
}, },
@ -406,3 +383,19 @@ export const CenteredContent: Story = {
`, `,
}), }),
}; };
export const Loading: Story = {
render: (args) => ({
props: args,
template: /* HTML */ `
<extension-container>
<popup-tab-navigation>
<popup-page [loading]="true">
<popup-header slot="header" pageTitle="Page Header"></popup-header>
Content would go here
</popup-page>
</popup-tab-navigation>
</extension-container>
`,
}),
};

View File

@ -1,7 +1,16 @@
<ng-content select="[slot=header]"></ng-content> <ng-content select="[slot=header]"></ng-content>
<main class="tw-bg-background-alt tw-flex-1 tw-overflow-y-auto tw-h-full"> <main class="tw-flex-1 tw-overflow-y-auto tw-h-full tw-relative tw-bg-background-alt">
<div class="tw-max-w-screen-sm tw-mx-auto tw-p-3 tw-overflow-y-auto tw-h-full"> <div
class="tw-max-w-screen-sm tw-mx-auto tw-p-3 tw-overflow-y-auto tw-h-full"
[ngClass]="{ 'tw-invisible': loading }"
>
<ng-content></ng-content> <ng-content></ng-content>
</div> </div>
<span
class="tw-absolute tw-inset-0 tw-flex tw-items-center tw-justify-center tw-text-main"
[ngClass]="{ 'tw-invisible': !loading }"
>
<i class="bwi bwi-spinner bwi-lg bwi-spin" [attr.aria-label]="loadingText"></i>
</span>
</main> </main>
<ng-content select="[slot=footer]"></ng-content> <ng-content select="[slot=footer]"></ng-content>

View File

@ -1,4 +1,7 @@
import { Component } from "@angular/core"; import { CommonModule } from "@angular/common";
import { Component, Input, inject } from "@angular/core";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@Component({ @Component({
selector: "popup-page", selector: "popup-page",
@ -7,5 +10,13 @@ import { Component } from "@angular/core";
host: { host: {
class: "tw-h-full tw-flex tw-flex-col tw-flex-1 tw-overflow-y-auto", class: "tw-h-full tw-flex tw-flex-col tw-flex-1 tw-overflow-y-auto",
}, },
imports: [CommonModule],
}) })
export class PopupPageComponent {} export class PopupPageComponent {
protected i18nService = inject(I18nService);
@Input() loading = false;
/** Accessible loading label for the spinner. Defaults to "loading" */
@Input() loadingText?: string = this.i18nService.t("loading");
}