diff --git a/.changeset/passkey-add-pending.md b/.changeset/passkey-add-pending.md
new file mode 100644
index 00000000000..a845151cc84
--- /dev/null
+++ b/.changeset/passkey-add-pending.md
@@ -0,0 +1,2 @@
+---
+---
diff --git a/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/__tests__/user-profile-passkeys-lifecycle.feature.test.tsx b/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/__tests__/user-profile-passkeys-lifecycle.feature.test.tsx
index 96fea87fb2c..dd98de38aff 100644
--- a/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/__tests__/user-profile-passkeys-lifecycle.feature.test.tsx
+++ b/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/__tests__/user-profile-passkeys-lifecycle.feature.test.tsx
@@ -82,6 +82,26 @@ describe('Passkey action errors', () => {
});
});
+describe('Adding a passkey', () => {
+ it('shows the Add button pending while the passkey request runs', async () => {
+ serveAccounts();
+ await renderWithClerk();
+ const creation = holdRequests('post', '/v1/me/passkeys');
+ const user = userEvent.setup();
+
+ try {
+ await user.click(screen.getByRole('button', { name: 'Add passkey' }));
+ await waitFor(() => expect(creation.requests).toHaveLength(1));
+ expect(screen.getByRole('button', { name: 'Add passkey' })).toHaveAttribute('aria-busy', 'true');
+ await waitFor(() => expect(screen.getByRole('progressbar')).toBeVisible());
+ } finally {
+ creation.fail('form_param_invalid', 'Credential failed');
+ }
+ await waitFor(() => expect(screen.getByRole('button', { name: 'Add passkey' })).toBeEnabled());
+ await waitFor(() => expect(screen.queryByRole('progressbar')).toBeNull());
+ });
+});
+
describe('Changing the active passkey account', () => {
it('clears the previous account Add error after a user switch', async () => {
serveAccounts();
diff --git a/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/user-profile-passkeys-section.view.tsx b/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/user-profile-passkeys-section.view.tsx
index d3425ae5af2..03080c24d74 100644
--- a/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/user-profile-passkeys-section.view.tsx
+++ b/packages/mosaic/src/features/user-profile/user-profile-passkeys-section/user-profile-passkeys-section.view.tsx
@@ -3,7 +3,7 @@ import type { Ref } from 'react';
import type { ConfirmController } from '../../../blocks/confirm';
import { Confirmation } from '../../../blocks/confirmation';
import { ReverificationDialog } from '../../../blocks/reverification';
-import { Button } from '../../../components/button';
+import { SubmitButton } from '../../../components/button';
import type { DialogFocusTarget } from '../../../components/dialog';
import { Field } from '../../../components/field';
import { Icon } from '../../../components/icon';
@@ -69,14 +69,15 @@ export function UserProfilePasskeysSectionView({
{onAdd ? (
-
+
) : null}