= {
+ render: (args) => Template(args, Spinner),
+ argTypes: {
+ disableSpin: { control: "boolean" },
+ },
+ args: {
+ disableSpin: false,
+ },
+};
+
export const AngleDownIcon = createIconStory("AngleDown");
export const AngleUpIcon = createIconStory("AngleUp");
export const BusinessIcon = createIconStory("Business");
@@ -58,4 +70,5 @@ export const FolderIcon = createIconStory("Folder");
export const GlobeIcon = createIconStory("Globe");
export const PencilSquareIcon = createIconStory("PencilSquare");
export const ShieldIcon = createIconStory("Shield");
+export const SpinnerIcon = SpinnerIconStory;
export const UserIcon = createIconStory("User");
diff --git a/apps/browser/src/autofill/content/components/notification/button-row.ts b/apps/browser/src/autofill/content/components/notification/button-row.ts
index 470147cb469..04b79c1951a 100644
--- a/apps/browser/src/autofill/content/components/notification/button-row.ts
+++ b/apps/browser/src/autofill/content/components/notification/button-row.ts
@@ -34,6 +34,7 @@ export type NotificationButtonRowProps = {
organizations?: OrgView[];
primaryButton: {
text: string;
+ isLoading?: boolean;
handlePrimaryButtonClick: (args: any) => void;
};
personalVaultIsAllowed: boolean;
diff --git a/apps/browser/src/autofill/content/components/notification/container.ts b/apps/browser/src/autofill/content/components/notification/container.ts
index cc7f0fc72c0..0c70e0da63c 100644
--- a/apps/browser/src/autofill/content/components/notification/container.ts
+++ b/apps/browser/src/autofill/content/components/notification/container.ts
@@ -29,6 +29,7 @@ export type NotificationContainerProps = NotificationBarIframeInitData & {
folders?: FolderView[];
headerMessage?: string;
i18n: I18n;
+ isLoading?: boolean;
organizations?: OrgView[];
personalVaultIsAllowed?: boolean;
notificationTestId: string;
@@ -44,6 +45,7 @@ export function NotificationContainer({
folders,
headerMessage,
i18n,
+ isLoading,
organizations,
personalVaultIsAllowed = true,
notificationTestId,
@@ -74,6 +76,7 @@ export function NotificationContainer({
collections,
folders,
i18n,
+ isLoading,
notificationType: type,
organizations,
personalVaultIsAllowed,
diff --git a/apps/browser/src/autofill/content/components/notification/footer.ts b/apps/browser/src/autofill/content/components/notification/footer.ts
index b47dd5cc094..d37547a6fae 100644
--- a/apps/browser/src/autofill/content/components/notification/footer.ts
+++ b/apps/browser/src/autofill/content/components/notification/footer.ts
@@ -16,6 +16,7 @@ export type NotificationFooterProps = {
collections?: CollectionView[];
folders?: FolderView[];
i18n: I18n;
+ isLoading?: boolean;
notificationType?: NotificationType;
organizations?: OrgView[];
personalVaultIsAllowed: boolean;
@@ -27,6 +28,7 @@ export function NotificationFooter({
collections,
folders,
i18n,
+ isLoading,
notificationType,
organizations,
personalVaultIsAllowed,
@@ -52,6 +54,7 @@ export function NotificationFooter({
i18n,
primaryButton: {
handlePrimaryButtonClick: handleSaveAction,
+ isLoading,
text: primaryButtonText,
},
personalVaultIsAllowed,
diff --git a/apps/browser/src/autofill/content/components/rows/button-row.ts b/apps/browser/src/autofill/content/components/rows/button-row.ts
index 041d0a6b696..8b4eabfec50 100644
--- a/apps/browser/src/autofill/content/components/rows/button-row.ts
+++ b/apps/browser/src/autofill/content/components/rows/button-row.ts
@@ -12,6 +12,7 @@ export type ButtonRowProps = {
theme: Theme;
primaryButton: {
text: string;
+ isLoading?: boolean;
handlePrimaryButtonClick: (args: any) => void;
};
selectButtons?: {
@@ -29,6 +30,7 @@ export function ButtonRow({ theme, primaryButton, selectButtons }: ButtonRowProp
${ActionButton({
handleClick: primaryButton.handlePrimaryButtonClick,
buttonText: primaryButton.text,
+ isLoading: primaryButton.isLoading,
theme,
})}
diff --git a/apps/browser/src/autofill/notification/bar.ts b/apps/browser/src/autofill/notification/bar.ts
index 275e6cb0721..285ae4aa257 100644
--- a/apps/browser/src/autofill/notification/bar.ts
+++ b/apps/browser/src/autofill/notification/bar.ts
@@ -249,25 +249,34 @@ async function initNotificationBar(message: NotificationBarWindowMessage) {
document.head.querySelectorAll('link[rel="stylesheet"]').forEach((node) => node.remove());
if (isVaultLocked) {
- return render(
- NotificationContainer({
- ...notificationBarIframeInitData,
- headerMessage,
- type: resolvedType,
- notificationTestId,
- theme: resolvedTheme,
- personalVaultIsAllowed: !personalVaultDisallowed,
- handleCloseNotification,
- handleSaveAction: (e) => {
- sendSaveCipherMessage(true);
+ const notificationConfig = {
+ ...notificationBarIframeInitData,
+ headerMessage,
+ type: resolvedType,
+ notificationTestId,
+ theme: resolvedTheme,
+ personalVaultIsAllowed: !personalVaultDisallowed,
+ handleCloseNotification,
+ handleEditOrUpdateAction,
+ i18n,
+ };
- // @TODO can't close before vault has finished decrypting, but can't leave open during long decrypt because it looks like the experience has failed
- },
- handleEditOrUpdateAction,
- i18n,
- }),
- document.body,
- );
+ const handleSaveAction = () => {
+ sendSaveCipherMessage(true);
+
+ render(
+ NotificationContainer({
+ ...notificationConfig,
+ handleSaveAction: () => {},
+ isLoading: true,
+ }),
+ document.body,
+ );
+ };
+
+ const UnlockNotification = NotificationContainer({ ...notificationConfig, handleSaveAction });
+
+ return render(UnlockNotification, document.body);
}
// Handle AtRiskPasswordNotification render