feat(ui): Add dev-mode test credential hint to sign-in/sign-up fields#9162
feat(ui): Add dev-mode test credential hint to sign-in/sign-up fields#9162alexcarpenter wants to merge 2 commits into
Conversation
In development, the email/phone fields on sign-in and sign-up now reveal an info hint on hover/focus that nudges developers toward Clerk test credentials and can insert a suggested test email or phone number.
🦋 Changeset detectedLatest commit: 2dadf50 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughDevelopment-only test credential hints are added to sign-in and sign-up email or phone fields. The hint displays guidance, verification information, and insertion actions, while phone inputs synchronize externally inserted values. ChangesDevelopment credential hints
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant FieldDevHint
participant SignInStart
participant SignUpForm
participant PhoneInputBase
Developer->>FieldDevHint: Focus or open an empty field hint
FieldDevHint->>Developer: Show test credential guidance
Developer->>FieldDevHint: Select insertion action
FieldDevHint->>SignInStart: Set test identifier
FieldDevHint->>SignUpForm: Set test email or phone
SignUpForm->>PhoneInputBase: Pass updated phone value
PhoneInputBase->>PhoneInputBase: Synchronize internal phone state
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
API Changes Report
Summary
No API Changes DetectedAll packages have stable APIs with no detected changes. Report generated by Break Check Last ran on |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ui/src/components/SignIn/SignInStart.tsx`:
- Around line 574-592: Extract the shared email and phone dev-hint factories
into a reusable utility, preserving the existing copy, labels, and test values.
In packages/ui/src/components/SignIn/SignInStart.tsx lines 574-592, replace the
inline ternary objects with createEmailTestHint/setValue or
createPhoneTestHint/setValue calls; in
packages/ui/src/components/SignUp/SignUpForm.tsx lines 89-95 and 107-113,
replace each corresponding inline object with the same shared helper and import
it.
In `@packages/ui/src/primitives/Button.tsx`:
- Around line 78-84: Update Button’s colorScheme type declaration to include the
warning literal alongside primary, secondary, neutral, and danger, making the
existing warning variant in the color scheme mapping accessible through the
typed API.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Repository UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 5d1cdc48-72b8-4837-8c07-956abd3e5b88
📒 Files selected for processing (8)
.changeset/dev-mode-test-credential-hint.mdpackages/ui/src/components/SignIn/SignInStart.tsxpackages/ui/src/components/SignUp/SignUpForm.tsxpackages/ui/src/elements/FieldControl.tsxpackages/ui/src/elements/FieldDevHint.tsxpackages/ui/src/elements/Form.tsxpackages/ui/src/elements/PhoneInput/index.tsxpackages/ui/src/primitives/Button.tsx
| const identifierDevHint = | ||
| identifierAttribute === 'phone_number' | ||
| ? { | ||
| text: 'Testing? Use a test phone number so you skip a real SMS. Verify it on the next screen with the code 424242.', | ||
| action: { | ||
| label: 'Insert test phone number', | ||
| onInsert: () => identifierField.setValue('+12015550100'), | ||
| }, | ||
| } | ||
| : identifierAttribute === 'email_address' || identifierAttribute === 'email_address_username' | ||
| ? { | ||
| text: 'Testing? Use a test email so you skip a real inbox. Verify it on the next screen with the code 424242.', | ||
| action: { | ||
| label: 'Insert test email', | ||
| onInsert: () => identifierField.setValue('your_email+clerk_test@example.com'), | ||
| }, | ||
| } | ||
| : undefined; | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Extract a shared factory for the dev-hint copy/actions to avoid triplicated literals.
The same hint text and test-credential values are hardcoded in three places across two files. Any future wording tweak or test-value change now needs three synchronized edits.
packages/ui/src/components/SignIn/SignInStart.tsx#L574-L592: replace the inline ternary literals with calls to a sharedcreateEmailTestHint(setValue)/createPhoneTestHint(setValue)helper.packages/ui/src/components/SignUp/SignUpForm.tsx#L89-L95: use the same shared email hint helper instead of the inline object.packages/ui/src/components/SignUp/SignUpForm.tsx#L107-L113: use the same shared phone hint helper instead of the inline object.
♻️ Example shared helper
// e.g. packages/ui/src/utils/devHints.ts
export const createEmailTestHint = (setValue: (v: string) => void): FieldDevHintValue => ({
text: 'Testing? Use a test email so you skip a real inbox. Verify it on the next screen with the code 424242.',
action: { label: 'Insert test email', onInsert: () => setValue('your_email+clerk_test@example.com') },
});
export const createPhoneTestHint = (setValue: (v: string) => void): FieldDevHintValue => ({
text: 'Testing? Use a test phone number so you skip a real SMS. Verify it on the next screen with the code 424242.',
action: { label: 'Insert test phone number', onInsert: () => setValue('+12015550100') },
});📍 Affects 2 files
packages/ui/src/components/SignIn/SignInStart.tsx#L574-L592(this comment)packages/ui/src/components/SignUp/SignUpForm.tsx#L89-L95packages/ui/src/components/SignUp/SignUpForm.tsx#L107-L113
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ui/src/components/SignIn/SignInStart.tsx` around lines 574 - 592,
Extract the shared email and phone dev-hint factories into a reusable utility,
preserving the existing copy, labels, and test values. In
packages/ui/src/components/SignIn/SignInStart.tsx lines 574-592, replace the
inline ternary objects with createEmailTestHint/setValue or
createPhoneTestHint/setValue calls; in
packages/ui/src/components/SignUp/SignUpForm.tsx lines 89-95 and 107-113,
replace each corresponding inline object with the same shared helper and import
it.
| warning: { | ||
| [vars.accent]: theme.colors.$warning500, | ||
| [vars.accentHover]: theme.colors.$warning600, | ||
| [vars.accentContrast]: theme.colors.$white, | ||
| [vars.border]: theme.colors.$warning500, | ||
| [vars.alpha]: theme.colors.$warningAlpha50, | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check whether 'warning' is added to the colorScheme prop type
rg -n "colorScheme" packages/ui/src/primitives/Button.tsxRepository: clerk/javascript
Length of output: 426
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Button.tsx colorScheme references =="
rg -n "colorScheme" packages/ui/src/primitives/Button.tsx
echo
echo "== Repository-wide 'colorScheme: warning' references =="
rg -n "colorScheme\\s*[:=]\\s*'warning'|colorScheme\\s*=\\s*\\{?\\s*'warning'|colorScheme=\\\"warning\\\"|colorScheme='warning'" packages/ui/src
echo
echo "== Button component usages passing warning =="
rg -n "<Button[^>]*colorScheme=\\{?'warning'|<Button[^>]*colorScheme=\\\"warning\\\"" packages/ui/srcRepository: clerk/javascript
Length of output: 777
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Button.tsx colorScheme references =="
rg -n "colorScheme" packages/ui/src/primitives/Button.tsx
echo
echo "== Repository-wide Button colorScheme='warning' usages =="
rg -n "colorScheme=['\"]warning['\"]" packages/ui/src
echo
echo "== Repository-wide Button JSX warning usages =="
rg -n "<Button[^>]*colorScheme=[^>]*warning" packages/ui/src
echo
echo "== Repository-wide widened colorScheme unions =="
rg -n "colorScheme\\?:[^\\n]*warning|colorScheme[^\\n]*\\|[^\\n]*warning" packages/ui/srcRepository: clerk/javascript
Length of output: 1632
Add warning to Button's colorScheme union. The new variant entry is unreachable through the typed API until colorScheme?: 'primary' | 'secondary' | 'neutral' | 'danger' | 'warning' is updated.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ui/src/primitives/Button.tsx` around lines 78 - 84, Update Button’s
colorScheme type declaration to include the warning literal alongside primary,
secondary, neutral, and danger, making the existing warning variant in the color
scheme mapping accessible through the typed API.
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/electron
@clerk/electron-passkeys
@clerk/eslint-plugin
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
…ed email The dev-mode test-credential hint now stays visible (as a warning) while the email/phone field holds a non-test value, and hides once it is a test credential. Inserting a test email transforms the currently typed address by adding the +clerk_test subaddress instead of replacing it.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ui/src/utils/clerkTestEmail.ts`:
- Around line 14-16: Update the Clerk test email detection around the existing
trimmed-email check to match clerk_test only as an exact subaddress segment in
the local part, excluding near-matches in segments or domains. Align the SignIn
and SignUp consumers’ checks with this exact matching behavior, and add
regression tests covering alex+clerk_testing@example.com and
alex@clerk_test.example.com.
In `@packages/ui/src/utils/clerkTestPhoneNumber.ts`:
- Around line 5-6: The isClerkTestPhoneNumber function currently matches only
the suffix, allowing incomplete or overlong values. Validate the normalized
phone number as exactly 10 digits or 11 digits prefixed with 1 before applying
the 55501xx test-number pattern, and add regression tests covering short and
overlong inputs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Repository UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: adc68cb1-4137-49a9-8242-aa407e7bedb1
📒 Files selected for processing (7)
packages/ui/src/components/SignIn/SignInStart.tsxpackages/ui/src/components/SignUp/SignUpForm.tsxpackages/ui/src/elements/FieldDevHint.tsxpackages/ui/src/utils/__tests__/clerkTestEmail.test.tspackages/ui/src/utils/__tests__/clerkTestPhoneNumber.test.tspackages/ui/src/utils/clerkTestEmail.tspackages/ui/src/utils/clerkTestPhoneNumber.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/ui/src/elements/FieldDevHint.tsx
- packages/ui/src/components/SignUp/SignUpForm.tsx
- packages/ui/src/components/SignIn/SignInStart.tsx
| if (trimmed.includes(CLERK_TEST_SUBADDRESS)) { | ||
| return trimmed; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Match clerk_test as an exact subaddress segment.
includes treats values such as alex+clerk_testing@example.com or alex@clerk_test.example.com as test credentials. The SignIn and SignUp consumers also use broad value.includes('+clerk_test') checks, so the hint is hidden for non-test values. Match the local-part segment exactly and add regression tests for near-miss values.
Proposed fix
- if (trimmed.includes(CLERK_TEST_SUBADDRESS)) {
+ const localPart = trimmed.split('@', 1)[0];
+ if (localPart.split('+').includes(CLERK_TEST_SUBADDRESS.slice(1))) {
return trimmed;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (trimmed.includes(CLERK_TEST_SUBADDRESS)) { | |
| return trimmed; | |
| } | |
| const localPart = trimmed.split('@', 1)[0]; | |
| if (localPart.split('+').includes(CLERK_TEST_SUBADDRESS.slice(1))) { | |
| return trimmed; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ui/src/utils/clerkTestEmail.ts` around lines 14 - 16, Update the
Clerk test email detection around the existing trimmed-email check to match
clerk_test only as an exact subaddress segment in the local part, excluding
near-matches in segments or domains. Align the SignIn and SignUp consumers’
checks with this exact matching behavior, and add regression tests covering
alex+clerk_testing@example.com and alex@clerk_test.example.com.
| export const isClerkTestPhoneNumber = (value: string): boolean => { | ||
| return /55501\d\d$/.test(value.replace(/\D/g, '')); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Require a complete US phone number before matching.
The suffix-only regex accepts partial input such as 5550100 and arbitrary longer values ending in the test range. Anchor the normalized value to 10 digits, or 11 digits beginning with 1, and add regression tests for short and overlong inputs.
Proposed fix
export const isClerkTestPhoneNumber = (value: string): boolean => {
- return /55501\d\d$/.test(value.replace(/\D/g, ''));
+ const digits = value.replace(/\D/g, '');
+ return /^(?:1)?\d{3}55501\d{2}$/.test(digits);
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const isClerkTestPhoneNumber = (value: string): boolean => { | |
| return /55501\d\d$/.test(value.replace(/\D/g, '')); | |
| export const isClerkTestPhoneNumber = (value: string): boolean => { | |
| const digits = value.replace(/\D/g, ''); | |
| return /^(?:1)?\d{3}55501\d{2}$/.test(digits); | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ui/src/utils/clerkTestPhoneNumber.ts` around lines 5 - 6, The
isClerkTestPhoneNumber function currently matches only the suffix, allowing
incomplete or overlong values. Validate the normalized phone number as exactly
10 digits or 11 digits prefixed with 1 before applying the 55501xx test-number
pattern, and add regression tests covering short and overlong inputs.
Description
Adds dev mode hints for prefilling email/phone number inputs with testing values.
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit