diff --git a/.changeset/ten-pigs-flash.md b/.changeset/ten-pigs-flash.md
new file mode 100644
index 00000000000..72f373e7b3c
--- /dev/null
+++ b/.changeset/ten-pigs-flash.md
@@ -0,0 +1,5 @@
+---
+"@clerk/clerk-js": patch
+---
+
+Support `phone_code` as first factor for the experimental UserVerification component.
diff --git a/packages/clerk-js/src/ui/components/UserVerification/UVFactorOnePhoneCodeCard.tsx b/packages/clerk-js/src/ui/components/UserVerification/UVFactorOnePhoneCodeCard.tsx
new file mode 100644
index 00000000000..9ba5c0b778f
--- /dev/null
+++ b/packages/clerk-js/src/ui/components/UserVerification/UVFactorOnePhoneCodeCard.tsx
@@ -0,0 +1,21 @@
+import type { PhoneCodeFactor } from '@clerk/types';
+
+import { Flow, localizationKeys } from '../../customizables';
+import type { UVFactorOneCodeCard } from './UVFactorOneCodeForm';
+import { UVFactorOneCodeForm } from './UVFactorOneCodeForm';
+
+type UVFactorOnePhoneCodeCardProps = UVFactorOneCodeCard & { factor: PhoneCodeFactor };
+
+export const UVFactorOnePhoneCodeCard = (props: UVFactorOnePhoneCodeCardProps) => {
+ return (
+
+
+
+ );
+};
diff --git a/packages/clerk-js/src/ui/components/UserVerification/UserVerificationFactorOne.tsx b/packages/clerk-js/src/ui/components/UserVerification/UserVerificationFactorOne.tsx
index 79d191c58ca..804ed28a183 100644
--- a/packages/clerk-js/src/ui/components/UserVerification/UserVerificationFactorOne.tsx
+++ b/packages/clerk-js/src/ui/components/UserVerification/UserVerificationFactorOne.tsx
@@ -11,6 +11,7 @@ import { AlternativeMethods } from './AlternativeMethods';
import { UserVerificationFactorOnePasswordCard } from './UserVerificationFactorOnePassword';
import { useUserVerificationSession, withUserVerificationSessionGuard } from './useUserVerificationSession';
import { UVFactorOneEmailCodeCard } from './UVFactorOneEmailCodeCard';
+import { UVFactorOnePhoneCodeCard } from './UVFactorOnePhoneCodeCard';
const factorKey = (factor: SignInFactor | null | undefined) => {
if (!factor) {
@@ -116,6 +117,15 @@ export function _UserVerificationFactorOne(): JSX.Element | null {
factor={currentFactor}
/>
);
+ case 'phone_code':
+ return (
+
+ );
default:
return ;
}
diff --git a/packages/clerk-js/src/ui/components/UserVerification/__tests__/UVFactorOne.test.tsx b/packages/clerk-js/src/ui/components/UserVerification/__tests__/UVFactorOne.test.tsx
index 87a27836eaa..5fc18ffb964 100644
--- a/packages/clerk-js/src/ui/components/UserVerification/__tests__/UVFactorOne.test.tsx
+++ b/packages/clerk-js/src/ui/components/UserVerification/__tests__/UVFactorOne.test.tsx
@@ -49,9 +49,29 @@ describe('UserVerificationFactorOne', () => {
getByText('Check your email');
getByLabelText(/Enter verification code/i);
});
+
+ expect(fixtures.session?.__experimental_prepareFirstFactorVerification).toHaveBeenCalledTimes(1);
});
- it.todo('renders the component for with strategy:phone_code');
+ it('renders the component for with strategy:phone_code', async () => {
+ const { wrapper, fixtures } = await createFixtures(f => {
+ f.withUser({ username: 'clerkuser' });
+ f.withPreferredSignInStrategy({ strategy: 'otp' });
+ });
+ fixtures.session?.__experimental_startVerification.mockResolvedValue({
+ status: 'needs_first_factor',
+ supportedFirstFactors: [{ strategy: 'password' }, { strategy: 'phone_code' }],
+ });
+ fixtures.session?.__experimental_prepareFirstFactorVerification.mockResolvedValue({});
+ const { getByLabelText, getByText } = render(, { wrapper });
+
+ await waitFor(() => {
+ getByText('Check your phone');
+ getByLabelText(/Enter verification code/i);
+ });
+
+ expect(fixtures.session?.__experimental_prepareFirstFactorVerification).toHaveBeenCalledTimes(1);
+ });
describe('Submitting', () => {
it('navigates to UserVerificationFactorTwo page when user submits first factor and second factor is enabled', async () => {
@@ -110,6 +130,7 @@ describe('UserVerificationFactorOne', () => {
await waitFor(() => {
expect(fixtures.clerk.setActive).toHaveBeenCalled();
});
+ expect(fixtures.session?.__experimental_attemptFirstFactorVerification).toHaveBeenCalledTimes(1);
});
});