-
Notifications
You must be signed in to change notification settings - Fork 435
chore(clerk-js): Keyless UI refactor #7834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: e2ebca3 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 |
📝 WalkthroughWalkthroughThis pull request updates the KeylessPrompt component and related testing infrastructure. The changes include a structural refactor of the KeylessPrompt component introducing a state machine pattern with new types (STATES) and utility functions (getCurrentState, getResolvedContent). The component rendering logic is replaced with a declarative, state-driven approach. The test page object for the keyless popover is updated to use role-based selectors instead of direct DOM queries. A new comprehensive test suite is added covering multiple state combinations and component behaviors. Test fixtures are expanded with a withClaimedAt helper, and integration tests are simplified by removing redundant assertions. 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. No actionable comments were generated in the recent review. 🎉 Comment |
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx`:
- Around line 296-303: The memoized claimUrlToDashboard in KeylessPrompt reads
window.location.href during render which breaks SSR; modify the useMemo to guard
access to window by checking typeof window !== 'undefined' (or the same guard
used elsewhere in this codebase) before appending return_url, and fallback to a
safe value (e.g., props.claimUrl or props.copyKeysUrl) when window is
unavailable; update the logic around claimUrlToDashboard, useMemo,
props.claimUrl and props.copyKeysUrl to only reference window.location.href on
the client.
| const claimUrlToDashboard = useMemo(() => { | ||
| if (claimed) { | ||
| return _props.copyKeysUrl; | ||
| return props.copyKeysUrl; | ||
| } | ||
|
|
||
| const url = new URL(_props.claimUrl); | ||
| // Clerk Dashboard accepts a `return_url` query param when visiting `/apps/claim`. | ||
| const url = new URL(props.claimUrl); | ||
| url.searchParams.append('return_url', window.location.href); | ||
| return url.href; | ||
| }, [claimed, _props.copyKeysUrl, _props.claimUrl]); | ||
| }, [claimed, props.copyKeysUrl, props.claimUrl]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Search for KeylessPrompt imports and usage across the codebase
rg -nP --type=tsx --type=ts 'KeylessPrompt\b' --max-count=50Repository: clerk/javascript
Length of output: 87
🏁 Script executed:
# Check if the file has any 'use client' directive or SSR markers
cat -n packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx | head -20Repository: clerk/javascript
Length of output: 894
🏁 Script executed:
# Look for SSR-related patterns in the codebase
rg -nP --type=tsx --type=ts "typeof window|'use client'|SSR" packages/ui/src --max-count=30Repository: clerk/javascript
Length of output: 87
🏁 Script executed:
# Search for KeylessPrompt without type specification
rg 'KeylessPrompt' -n --max-count=30Repository: clerk/javascript
Length of output: 2419
🏁 Script executed:
# Check if file has 'use client' directive anywhere
grep -n "'use client'" packages/ui/src/components/devPrompts/KeylessPrompt/index.tsxRepository: clerk/javascript
Length of output: 42
🏁 Script executed:
# Get full file to understand context
wc -l packages/ui/src/components/devPrompts/KeylessPrompt/index.tsxRepository: clerk/javascript
Length of output: 125
🏁 Script executed:
# Check the export wrapper of KeylessPrompt (around line 570)
sed -n '565,576p' packages/ui/src/components/devPrompts/KeylessPrompt/index.tsxRepository: clerk/javascript
Length of output: 268
🏁 Script executed:
# Check the Components.tsx file where KeylessPrompt is used (around line 709)
sed -n '700,720p' packages/ui/src/Components.tsxRepository: clerk/javascript
Length of output: 1059
🏁 Script executed:
# Check if the parent UI component or Components.tsx has 'use client'
head -30 packages/ui/src/Components.tsxRepository: clerk/javascript
Length of output: 1208
🏁 Script executed:
# Check the broader context of lazyModules setup
head -30 packages/ui/src/lazyModules/components.tsRepository: clerk/javascript
Length of output: 2610
🏁 Script executed:
# Check if Components.tsx has 'use client' directive anywhere in the file
grep -n "use client" packages/ui/src/Components.tsxRepository: clerk/javascript
Length of output: 42
🏁 Script executed:
# Check the package.json for UI package to understand SSR intent
cat packages/ui/package.json | head -50Repository: clerk/javascript
Length of output: 1494
🏁 Script executed:
# Look at the problematic line context more closely (lines 290-310)
sed -n '290,310p' packages/ui/src/components/devPrompts/KeylessPrompt/index.tsxRepository: clerk/javascript
Length of output: 929
🏁 Script executed:
# Search for other SSR guards in the codebase (typeof window checks)
rg "typeof window" packages/ui/src --max-count=20Repository: clerk/javascript
Length of output: 927
Add SSR guard before accessing window.location.href to prevent server-side crashes.
Lines 296-303 access window.location.href during render in a useMemo. The @clerk/ui package explicitly declares "react-server" export support and KeylessPrompt is rendered from Components.tsx without a 'use client' directive, meaning it can execute on the server. This will crash during SSR. Add the guard pattern used elsewhere in the codebase:
const claimUrlToDashboard = useMemo(() => {
if (claimed) {
return props.copyKeysUrl;
}
const url = new URL(props.claimUrl);
- url.searchParams.append('return_url', window.location.href);
+ if (typeof window !== 'undefined') {
+ url.searchParams.append('return_url', window.location.href);
+ }
return url.href;
}, [claimed, props.copyKeysUrl, props.claimUrl]);🤖 Prompt for AI Agents
In `@packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx` around lines
296 - 303, The memoized claimUrlToDashboard in KeylessPrompt reads
window.location.href during render which breaks SSR; modify the useMemo to guard
access to window by checking typeof window !== 'undefined' (or the same guard
used elsewhere in this codebase) before appending return_url, and fallback to a
safe value (e.g., props.claimUrl or props.copyKeysUrl) when window is
unavailable; update the logic around claimUrlToDashboard, useMemo,
props.claimUrl and props.copyKeysUrl to only reference window.location.href on
the client.
Description
Migrate #7798 to Core 3
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit
Improvements
Testing