-
Notifications
You must be signed in to change notification settings - Fork 402
chore(clerk-js): Remove secret key column in API keys component #7107
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
🦋 Changeset detectedLatest commit: 6fceef4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 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.
|
WalkthroughReplaces persistent API key secret visibility with a one-time modal shown immediately after creation. Removes server-side secret fetch method, surfaces secret on create responses, adds modal components and element descriptors, updates types and tests, and extends localization keys across many locales. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as API Keys UI
participant API as Backend API
participant Modal as Copy Modal
rect rgb(230,245,255)
Note over User,UI: New flow — one-time secret display
User->>UI: Click "Create API Key"
UI->>API: POST /api_keys (name, scopes)
API-->>UI: { id, name, secret, ... }
UI->>Modal: Open with secret
User->>Modal: Click "Copy" → clipboard
Modal-->>User: Copy confirmation
User->>Modal: Click "Copy & Close"
Modal->>UI: Close modal
end
rect rgb(255,240,230)
Note over User,UI: Old flow (removed)
User->>UI: View API Keys table
UI->>API: GET /api_keys/{id}/secret
API-->>UI: { secret }
UI->>User: Display secret (repeatable)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
39-43: Localize revoke input and handle API errors
- Replace hard-coded label/placeholder with localization keys.
- Wrap revoke() in try/catch and use handleError to surface failures.
Example:
- const revokeField = useFormControl('apiKeyRevokeConfirmation', '', { - type: 'text', - label: `Type "Revoke" to confirm`, - placeholder: 'Revoke', - isRequired: true, - }); + const revokeField = useFormControl('apiKeyRevokeConfirmation', '', { + type: 'text', + label: localizationKeys('formFieldLabel__confirmDeletion'), + placeholder: localizationKeys('apiKeys.revokeConfirmation.confirmationText'), + isRequired: true, + }); @@ - await clerk.apiKeys.revoke({ apiKeyID: apiKeyId }); + try { + await clerk.apiKeys.revoke({ apiKeyID: apiKeyId }); + } catch (e) { + // Use the standard error utility to report and localize the error + // handleError(e); + return; + }Note: import and exact handleError path per project conventions. Based on coding guidelines.
Also applies to: 52-63
♻️ Duplicate comments (1)
packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
13-15: Fix a11y and form behavior; add return type (same as previously requested)
- Remove tabIndex={-1} to keep the button focusable.
- Add aria-label and type='button' to avoid accidental form submit.
- Add explicit return type for the exported component.
-export const ClipboardInput = (props: ClipboardInputProps) => { +export const ClipboardInput = (props: ClipboardInputProps): JSX.Element => { @@ - <Button + <Button elementDescriptor={descriptors.formFieldInputCopyToClipboardButton} variant='ghost' - tabIndex={-1} onClick={onCopy} + aria-label='Copy to clipboard' + type='button' sx={{ position: 'absolute', right: 0, }} >Optional: defensively coerce value for useClipboard:
- const { onCopy, hasCopied } = useClipboard(value as string); + const { onCopy, hasCopied } = useClipboard(String(value ?? ''));Also applies to: 30-46
🧹 Nitpick comments (6)
packages/localizations/src/he-IL.ts (1)
20-24: LGTM - Structure is correct for the new copy secret modal.The nested
copySecretobject correctly extends the API keys localization with the required fields for the one-time secret display modal. While the values areundefined(no Hebrew translations provided yet), this is consistent with the community-contributed nature of this file where many translations are pending.Consider providing Hebrew translations for these new fields to improve the user experience for Hebrew-speaking users, though this can be deferred to a future contribution.
packages/localizations/src/es-UY.ts (2)
20-24: Structure looks good; consider adding Spanish translations.The
copySecretnested object follows the established pattern and correctly implements the localization structure for the one-time API key secret display feature. The undefined values are consistent with this file's community-maintained status.However, since this is a security-critical feature, providing Spanish translations for these fields would significantly improve the user experience for Uruguayan Spanish speakers.
Consider adding translations for:
formButtonPrimary__copyAndClose: e.g., "Copiar y cerrar"formHint: Appropriate hint text about the one-time nature of the secret displayformTitle: e.g., "Clave secreta de API" or similarcopySecret: { - formButtonPrimary__copyAndClose: undefined, - formHint: undefined, - formTitle: undefined, + formButtonPrimary__copyAndClose: 'Copiar y cerrar', + formHint: 'Guardá esta clave de forma segura. Solo se mostrará una vez.', + formTitle: 'Clave secreta de API', },
230-230: Label field correctly added; translation recommended.The
formFieldLabel__apiKeyfield is properly positioned and follows the established naming convention. The undefined value is consistent with the file's current state.Consider adding a Spanish translation to improve UX:
- formFieldLabel__apiKey: undefined, + formFieldLabel__apiKey: 'Clave de API',integration/tests/machine-auth/component.test.ts (1)
133-147: Consider moving permission cleanup to ensure it runs even on test failure.The clipboard permissions are granted and cleared within the test flow, but if the test fails before reaching line 146, permissions may not be cleaned up. Consider using a try-finally block or moving the cleanup to an appropriate lifecycle hook.
Example approach:
- // Grant clipboard permissions before clicking the button await context.grantPermissions(['clipboard-read']); + + try { + // Click "Copy & Close" button which will copy the secret and close the modal + const copyAndCloseButton = copyModal.locator('.cl-apiKeysCopyModalSubmitButton'); + await copyAndCloseButton.waitFor({ state: 'attached' }); + await copyAndCloseButton.click(); - // Click "Copy & Close" button which will copy the secret and close the modal - const copyAndCloseButton = copyModal.locator('.cl-apiKeysCopyModalSubmitButton'); - await copyAndCloseButton.waitFor({ state: 'attached' }); - await copyAndCloseButton.click(); + // Wait for modal to close + await copyModal.waitFor({ state: 'detached' }); - // Wait for modal to close - await copyModal.waitFor({ state: 'detached' }); + // Read clipboard contents to verify the secret was copied + const clipboardText = await page.evaluate('navigator.clipboard.readText()'); + expect(clipboardText).toBe(secret); + } finally { + await context.clearPermissions(); + } - - // Read clipboard contents to verify the secret was copied - const clipboardText = await page.evaluate('navigator.clipboard.readText()'); - await context.clearPermissions(); - expect(clipboardText).toBe(secret);packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (2)
32-36: Use a more descriptive ID for the form control.The form control ID is set to
'name', but this field displays the API key secret, not a name. Consider using a more descriptive identifier like'apiKeySecret'or'apiKey'to improve code clarity and avoid potential conflicts.Apply this diff:
- const apiKeyField = useFormControl('name', apiKeySecret, { + const apiKeyField = useFormControl('apiKeySecret', apiKeySecret, { type: 'text', label: localizationKeys('formFieldLabel__apiKey'), isRequired: false, });
76-84: Consider simplifying the read-only field implementation.The
useFormControlhook provides interactive form field machinery (onChange, onFocus, validation, etc.), butClipboardInputis inherently read-only and disabled. The form control logic isn't actively used here. Consider whether a simpler approach with just a label and theClipboardInputwould be more appropriate.Alternative approach:
<Form.ControlRow elementDescriptor={descriptors.apiKeysCopyModalInput} sx={{ flex: 1 }} > <Form.Label localizationKey={localizationKeys('formFieldLabel__apiKey')} /> <ClipboardInput value={apiKeySecret} readOnly sx={{ width: '100%' }} copyIcon={ClipboardOutline} copiedIcon={Check} /> </Form.ControlRow>However, if
Form.CommonInputWrapperprovides necessary styling or structure for consistency with other forms, the current approach is acceptable.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (59)
integration/tests/machine-auth/component.test.ts(2 hunks)packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx(5 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx(2 hunks)packages/clerk-js/src/ui/components/ApiKeys/utils.ts(1 hunks)packages/clerk-js/src/ui/customizables/elementDescriptors.ts(1 hunks)packages/clerk-js/src/ui/elements/ClipboardInput.tsx(2 hunks)packages/clerk-js/src/ui/elements/Form.tsx(1 hunks)packages/localizations/src/ar-SA.ts(2 hunks)packages/localizations/src/be-BY.ts(2 hunks)packages/localizations/src/bg-BG.ts(2 hunks)packages/localizations/src/bn-IN.ts(2 hunks)packages/localizations/src/ca-ES.ts(2 hunks)packages/localizations/src/cs-CZ.ts(2 hunks)packages/localizations/src/da-DK.ts(2 hunks)packages/localizations/src/de-DE.ts(2 hunks)packages/localizations/src/el-GR.ts(2 hunks)packages/localizations/src/en-GB.ts(2 hunks)packages/localizations/src/en-US.ts(2 hunks)packages/localizations/src/es-CR.ts(2 hunks)packages/localizations/src/es-ES.ts(2 hunks)packages/localizations/src/es-MX.ts(2 hunks)packages/localizations/src/es-UY.ts(2 hunks)packages/localizations/src/fa-IR.ts(2 hunks)packages/localizations/src/fi-FI.ts(2 hunks)packages/localizations/src/fr-FR.ts(2 hunks)packages/localizations/src/he-IL.ts(2 hunks)packages/localizations/src/hi-IN.ts(2 hunks)packages/localizations/src/hr-HR.ts(2 hunks)packages/localizations/src/hu-HU.ts(2 hunks)packages/localizations/src/id-ID.ts(2 hunks)packages/localizations/src/is-IS.ts(2 hunks)packages/localizations/src/it-IT.ts(2 hunks)packages/localizations/src/ja-JP.ts(2 hunks)packages/localizations/src/kk-KZ.ts(2 hunks)packages/localizations/src/ko-KR.ts(2 hunks)packages/localizations/src/mn-MN.ts(2 hunks)packages/localizations/src/ms-MY.ts(2 hunks)packages/localizations/src/nb-NO.ts(2 hunks)packages/localizations/src/nl-BE.ts(2 hunks)packages/localizations/src/nl-NL.ts(2 hunks)packages/localizations/src/pl-PL.ts(2 hunks)packages/localizations/src/pt-BR.ts(2 hunks)packages/localizations/src/pt-PT.ts(2 hunks)packages/localizations/src/ro-RO.ts(2 hunks)packages/localizations/src/ru-RU.ts(2 hunks)packages/localizations/src/sk-SK.ts(2 hunks)packages/localizations/src/sr-RS.ts(2 hunks)packages/localizations/src/sv-SE.ts(2 hunks)packages/localizations/src/ta-IN.ts(2 hunks)packages/localizations/src/te-IN.ts(2 hunks)packages/localizations/src/th-TH.ts(2 hunks)packages/localizations/src/tr-TR.ts(2 hunks)packages/localizations/src/uk-UA.ts(2 hunks)packages/localizations/src/vi-VN.ts(2 hunks)packages/localizations/src/zh-CN.ts(2 hunks)packages/localizations/src/zh-TW.ts(2 hunks)packages/shared/src/types/appearance.ts(1 hunks)packages/shared/src/types/localization.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (33)
- packages/localizations/src/kk-KZ.ts
- packages/localizations/src/is-IS.ts
- packages/localizations/src/es-MX.ts
- packages/localizations/src/mn-MN.ts
- packages/localizations/src/ru-RU.ts
- packages/localizations/src/tr-TR.ts
- packages/localizations/src/en-US.ts
- packages/localizations/src/pt-BR.ts
- packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
- packages/localizations/src/de-DE.ts
- packages/localizations/src/es-ES.ts
- packages/localizations/src/hr-HR.ts
- packages/localizations/src/it-IT.ts
- packages/localizations/src/uk-UA.ts
- packages/localizations/src/es-CR.ts
- packages/localizations/src/th-TH.ts
- packages/localizations/src/ar-SA.ts
- packages/localizations/src/zh-TW.ts
- packages/localizations/src/ms-MY.ts
- packages/localizations/src/fi-FI.ts
- packages/localizations/src/pl-PL.ts
- packages/localizations/src/nb-NO.ts
- packages/localizations/src/fa-IR.ts
- packages/localizations/src/ca-ES.ts
- packages/localizations/src/en-GB.ts
- packages/localizations/src/ja-JP.ts
- packages/localizations/src/sr-RS.ts
- packages/localizations/src/pt-PT.ts
- packages/localizations/src/hu-HU.ts
- packages/localizations/src/fr-FR.ts
- packages/shared/src/types/localization.ts
- packages/localizations/src/bn-IN.ts
- packages/localizations/src/nl-BE.ts
🧰 Additional context used
📓 Path-based instructions (14)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsxpackages/clerk-js/src/ui/customizables/elementDescriptors.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/utils.tspackages/localizations/src/zh-CN.tspackages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/localizations/src/vi-VN.tspackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tsintegration/tests/machine-auth/component.test.tspackages/localizations/src/id-ID.tspackages/shared/src/types/appearance.tspackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/clerk-js/src/ui/elements/Form.tsxpackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/clerk-js/src/ui/customizables/elementDescriptors.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
packages/localizations/**/*
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Localization files must be placed in 'packages/localizations/'.
Files:
packages/localizations/src/zh-CN.tspackages/localizations/src/vi-VN.tspackages/localizations/src/ko-KR.tspackages/localizations/src/el-GR.tspackages/localizations/src/he-IL.tspackages/localizations/src/hi-IN.tspackages/localizations/src/nl-NL.tspackages/localizations/src/id-ID.tspackages/localizations/src/sv-SE.tspackages/localizations/src/cs-CZ.tspackages/localizations/src/bg-BG.tspackages/localizations/src/be-BY.tspackages/localizations/src/da-DK.tspackages/localizations/src/ro-RO.tspackages/localizations/src/es-UY.tspackages/localizations/src/sk-SK.tspackages/localizations/src/te-IN.tspackages/localizations/src/ta-IN.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsxpackages/clerk-js/src/ui/elements/ClipboardInput.tsxpackages/clerk-js/src/ui/elements/Form.tsx
integration/**
📄 CodeRabbit inference engine (.cursor/rules/global.mdc)
Framework integration templates and E2E tests should be placed under the integration/ directory
Files:
integration/tests/machine-auth/component.test.ts
integration/**/*
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
End-to-end tests and integration templates must be located in the 'integration/' directory.
Files:
integration/tests/machine-auth/component.test.ts
integration/**/*.{test,spec}.{js,ts}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Integration tests should use Playwright.
Files:
integration/tests/machine-auth/component.test.ts
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
Append new element descriptors to APPEARANCE_KEYS in packages/clerk-js/src/ui/customizables/elementDescriptors.ts
Files:
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
🧠 Learnings (1)
📚 Learning: 2025-07-18T15:25:18.331Z
Learnt from: CR
Repo: clerk/javascript PR: 0
File: .cursor/rules/clerk-js-ui.mdc:0-0
Timestamp: 2025-07-18T15:25:18.331Z
Learning: Applies to packages/clerk-js/src/ui/customizables/elementDescriptors.ts : Append new element descriptors to APPEARANCE_KEYS in packages/clerk-js/src/ui/customizables/elementDescriptors.ts
Applied to files:
packages/clerk-js/src/ui/customizables/elementDescriptors.ts
🧬 Code graph analysis (4)
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
packages/clerk-js/src/ui/styledSystem/types.ts (1)
ThemableCssProp(58-58)
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
getApiKeyModalContainerStyles(8-29)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (6)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/elements/Modal.tsx (1)
Modal(25-108)packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
getApiKeyModalContainerStyles(8-29)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
packages/clerk-js/src/ui/elements/ClipboardInput.tsx (2)
packages/clerk-js/src/ui/styledSystem/types.ts (1)
PropsOfComponent(58-58)packages/clerk-js/src/ui/customizables/index.ts (1)
Flex(16-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (35)
packages/localizations/src/nl-NL.ts (2)
20-24: LGTM! New localization structure added correctly.The new
copySecretnested object underapiKeysis properly structured and follows the established pattern of usingundefinedfor untranslated strings in this community-maintained locale file. This addition supports the new one-time API key secret display modal feature.
228-228: LGTM! Form field label added correctly.The new
formFieldLabel__apiKeyfield is properly placed among the other form field labels and follows the consistent pattern of usingundefinedfor missing translations in this community-maintained locale.packages/localizations/src/te-IN.ts (2)
20-24: LGTM! New API key copy secret localization structure added correctly.The new
copySecretnested object follows the correct structure and naming conventions. Theundefinedvalues are appropriate for this community-contributed locale, allowing fallback to the default language until Telugu translations are provided.
228-228: LGTM! API key form field label added correctly.The new
formFieldLabel__apiKeyfield is correctly placed in the form field labels section and follows the established naming convention. Theundefinedvalue is appropriate for this community-contributed locale.packages/localizations/src/be-BY.ts (2)
20-24: LGTM! Localization structure correctly added for one-time secret display.The
copySecretnested object is properly structured to support the new one-time API key secret display modal. The field names follow established conventions, andundefinedvalues are appropriate for this community-maintained locale pending translation.
230-230: LGTM! API key form field label correctly added.The
formFieldLabel__apiKeyfield is properly placed among other form field labels and follows the established naming convention. Theundefinedvalue is appropriate for this community-maintained locale.packages/localizations/src/ta-IN.ts (2)
20-24: Structure for "copy secret" modal added correctly.The nested
copySecretobject with its three fields follows the existing naming conventions and aligns with the PR's objective to support one-time secret display functionality. Theundefinedvalues indicate that Tamil translations are pending, which is acceptable for this community-contributed locale file (as noted in the file's disclaimer).
229-229: API key label field added correctly.The
formFieldLabel__apiKeyfield follows the established naming pattern and is positioned logically within the form field labels section. Theundefinedvalue indicates that a Tamil translation is pending, consistent with other untranslated fields in this community-contributed locale file.packages/localizations/src/he-IL.ts (1)
228-228: LGTM - Correctly adds API key form field label.The
formFieldLabel__apiKeyfield is properly placed within the form field labels section and follows the established naming convention. Like other fields in this community-contributed localization file, the Hebrew translation is pending (undefined).packages/localizations/src/id-ID.ts (2)
20-24: LGTM! Structure follows established patterns.The new
copySecretobject is correctly structured and follows the same pattern as other nested objects in this file (e.g.,revokeConfirmationat lines 48-53). Theundefinedvalues are appropriate for this community-maintained localization file awaiting Indonesian translations.
228-228: LGTM! Correctly placed and named.The new
formFieldLabel__apiKeyfield follows the established naming convention and is appropriately placed among other form field labels. Theundefinedvalue is consistent with this community-maintained localization file.packages/localizations/src/el-GR.ts (2)
20-24: LGTM! Structure is consistent with localization patterns.The new
copySecretnested group follows the established structure and naming conventions. Theundefinedvalues are appropriate for this community-contributed locale—translations can be provided by Greek-speaking contributors in the future.
229-229: LGTM! Consistent placement and naming.The
formFieldLabel__apiKeyfield is correctly placed alongside other form field labels and follows the established naming convention. Theundefinedvalue is expected for this community-contributed locale.packages/localizations/src/da-DK.ts (2)
20-24: Structural changes look good.The addition of the
copySecretobject underapiKeysaligns with the PR objective to display API key secrets one-time after creation. The field names follow proper naming conventions and the structure matches the expected localization pattern.Note: The
undefinedvalues mean Danish users will see fallback strings (likely English) for these new features, which is acceptable for a community-contributed localization file per the disclaimer at the top of the file.
229-229: Field addition is correct.The
formFieldLabel__apiKeyfield is properly placed among other form field labels and follows the established naming convention. This supports the new API key UI elements introduced in this PR.packages/localizations/src/sv-SE.ts (2)
20-24: LGTM! Structure is correct for the new API key secret copy feature.The nested
copySecretgroup follows the established localization pattern and aligns with the PR's one-time secret display functionality. Theundefinedvalues are acceptable for this community-maintained locale file per the disclaimer at the top—Swedish users will see fallback translations until community contributors provide Swedish text.
229-229: LGTM! New form field label follows conventions.The
formFieldLabel__apiKeykey follows the established naming pattern and is correctly positioned among other form field labels. Theundefinedvalue is consistent with this community-maintained file.packages/localizations/src/hi-IN.ts (2)
20-24: LGTM! Structure is correct for the one-time API key secret modal.The new
copySecretnested object underapiKeysfollows the correct structure for the one-time secret display feature. Theundefinedvalues are consistent with this file's pattern as a community-contributed locale where translations are not fully provided.
228-228: LGTM! Correctly adds the API key field label.The new
formFieldLabel__apiKeyfield is properly placed at the root level, following the naming convention and pattern used throughout the file. Theundefinedvalue is appropriate for this community-contributed locale.packages/localizations/src/ko-KR.ts (2)
20-24: LGTM! Structure and placement are correct.The new
copySecretobject is properly nested withinapiKeysand follows the established naming conventions. Theundefinedvalues are expected for this community-contributed localization file as noted in the disclaimer.
229-229: LGTM! Consistent placement and naming.The new
formFieldLabel__apiKeykey is correctly placed at the root level alongside otherformFieldLabel__*keys, following the established pattern in this localization file.packages/localizations/src/cs-CZ.ts (2)
20-24: Structure is correct; translations pending.The new
copySecretlocalization group is properly structured and follows established naming conventions. Theundefinedvalues are consistent with the file's disclaimer indicating this is a community-maintained localization that may have incomplete translations.Note: Czech translations for the new API key secret copy modal are missing. While this is acceptable given the community-maintained nature of this locale, consider tracking these for future translation completion to ensure Czech users have a complete experience.
233-233: Field addition is correct; translation missing.The new
formFieldLabel__apiKeyfield is properly placed and follows the established naming convention for form field labels. Theundefinedvalue is consistent with this locale's pattern for untranslated strings.As with the
copySecretgroup, consider adding this to the translation backlog for Czech locale completion.packages/localizations/src/ro-RO.ts (2)
20-24: LGTM: Copy secret modal localization structure added correctly.The new
copySecretnested object follows the established pattern and supports the one-time API key secret display feature. Usingundefinedvalues is appropriate for this community-contributed localization file, as stated in the file header disclaimer.
235-235: LGTM: API key form field label added correctly.The new
formFieldLabel__apiKeyproperty is properly placed among other form field labels and follows the established naming convention. Theundefinedvalue is appropriate given this is a community-contributed localization file.packages/localizations/src/vi-VN.ts (2)
233-233: LGTM: Form field label key added in correct location.The
formFieldLabel__apiKeyfield is properly placed within the form field labels section with appropriate naming convention. Theundefinedvalue is consistent with other untranslated strings in this community-contributed locale file.
20-24: Localization structure correctly aligned with source locale.The
copySecretnested group in vi-VN.ts has the correct structure matching the English locale, with appropriately named fields (formButtonPrimary__copyAndClose,formHint,formTitle). The undefined values are expected for this community-contributed file where Vietnamese translations are pending—the application will automatically fall back to English text for these strings.packages/localizations/src/bg-BG.ts (1)
20-24: Locales surface aligned for copy-secret flowKeys and shapes look correct; OK to ship with undefined placeholders (falls back to default locale). Please ensure all locales include these keys consistently.
Also applies to: 229-229
packages/localizations/src/zh-CN.ts (1)
20-24: Locales surface aligned for copy-secret flowAdditions match shared typings and other locales. Good to merge.
Also applies to: 228-229
packages/localizations/src/sk-SK.ts (1)
20-24: Locales surface aligned for copy-secret flowKeys are correct and consistent. Approved.
Also applies to: 229-229
packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx (1)
75-76: Centralized modal container styling LGTMUsing getApiKeyModalContainerStyles improves consistency. Good change.
packages/shared/src/types/appearance.ts (1)
633-636: Appearance types updated for API key copy modalNew element entries look correct and align with UI usage.
packages/clerk-js/src/ui/customizables/elementDescriptors.ts (1)
498-501: Descriptors synced with new appearance keysAdditions are correct and camelCase. Good to go.
packages/clerk-js/src/ui/components/ApiKeys/utils.ts (1)
1-29: LGTM!The utility function is well-structured with clear JSDoc documentation. The conditional styling logic correctly handles both custom modal root and default scenarios, and the type safety is properly maintained with
ThemableCssProp.packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
49-96: Excellent accessibility and security implementation.The modal correctly uses
role='alertdialog'for accessibility andcanCloseModal={false}to ensure users cannot accidentally dismiss the one-time secret display without explicitly copying it. All user-facing text is properly localized, and element descriptors follow the camelCase convention for consistent theming.
This comment has been minimized.
This comment has been minimized.
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
🧹 Nitpick comments (2)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (2)
31-35: Simplify:useFormControlappears unnecessary for read-only display.The form control state is initialized with
apiKeySecretbut never modified, and theClipboardInputreceives its value directly (line 76) rather than from the form control state. Since this is a read-only display, consider removinguseFormControland passing only the label toForm.CommonInputWrapper.If the label is the only needed metadata, refactor to:
- const apiKeyField = useFormControl('name', apiKeySecret, { - type: 'text', - label: localizationKeys('formFieldLabel__apiKey'), - isRequired: false, - }); + const label = localizationKeys('formFieldLabel__apiKey');Then update the wrapper:
- <Form.CommonInputWrapper {...apiKeyField.props}> + <Form.CommonInputWrapper label={label}> <ClipboardInput value={apiKeySecret} readOnly sx={{ width: '100%' }} copyIcon={ClipboardOutline} copiedIcon={Check} /> </Form.CommonInputWrapper>Note: Verify that
Form.CommonInputWrapperaccepts a simplelabelprop. If it requires the full form control props structure, this change may not be applicable and the current pattern is acceptable despite appearing redundant.
31-31: Use a more descriptive form control ID.The form control ID is set to
'name', which doesn't clearly describe the field's purpose. Consider using'apiKeySecret'or'apiKey'for better semantic clarity.Apply this diff:
- const apiKeyField = useFormControl('name', apiKeySecret, { + const apiKeyField = useFormControl('apiKeySecret', apiKeySecret, {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/clerk-js/src/ui/components/ApiKeys/RevokeAPIKeyConfirmationModal.tsx
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsxpackages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
🧬 Code graph analysis (2)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
packages/clerk-js/src/ui/elements/Modal.tsx (1)
Modal(25-108)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (6)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
ApiKeyModal(36-44)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/Form.tsx (1)
Form(309-322)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (2)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
48-94: Security and UX implementation aligns with PR objectives.The modal correctly implements one-time secret display:
canCloseModal={false}prevents accidental dismissal before copyingrole='alertdialog'provides appropriate accessibility semanticshandleSubmitensures the secret is copied before closing- Read-only
ClipboardInputprevents modificationThis aligns with the security enhancement described in USER-3698.
packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
1-44: LGTM! Clean portal-scoped modal wrapper implementation.The
ApiKeyModalcomponent provides a well-structured abstraction for rendering modals within scoped containers (e.g., UserProfile, OrganizationProfile):
getScopedPortalContainerStylescorrectly handles both document-root and scoped portal scenarios with appropriate positioning (absolute vs. fixed) and backdrop styling.- JSDoc clearly documents the rationale for custom container styles.
- Props are properly typed by extending
Modalprops.- Style merging via array syntax allows consumer-provided
containerSxto override defaults.
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: 0
♻️ Duplicate comments (2)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (2)
71-76: Reuse of list cache key for mutation causes cache conflicts and stale list data.This issue was flagged in a previous review but remains unaddressed. Using
cacheKeyfor both the list query and the create mutation can cause:
- Cache shape conflicts (list returns array/paginated data, create returns a single API key object)
- The newly created API key won't appear in the list until manual refresh
Apply this fix:
+import { useSWRConfig } from 'swr'; + export const APIKeysPage = ({ subject, perPage, revokeModalRoot }: APIKeysPageProps) => { // ... existing code ... const clerk = useClerk(); const { data: createdApiKey, trigger: createApiKey, isMutating, - } = useSWRMutation(cacheKey, (_key, { arg }: { arg: CreateAPIKeyParams }) => clerk.apiKeys.create(arg)); + } = useSWRMutation(`${cacheKey}/create`, (_key, { arg }: { arg: CreateAPIKeyParams }) => clerk.apiKeys.create(arg)); + const { mutate } = useSWRConfig();Then in
handleCreateApiKey, revalidate the list after successful creation:const handleCreateApiKey = async (params: OnCreateParams) => { try { await createApiKey({ ...params, subject, }); + await mutate(cacheKey); // Refresh the list card.setError(undefined); setIsCopyModalOpen(true); } catch (err: any) {
160-167: Gate modal opening on secret presence—secret field is optional and can be undefined.The
secretfield inAPIKeyResourceis defined as optional (secret?: string;in APIKey.ts). WhenhandleCreateApiKeysucceeds, the modal opens unconditionally without verifying that the secret was returned from the backend. If the API response omits the secret field,CopyApiKeyModaldisplays an empty field and the user cannot retrieve their newly created API key.Update
handleCreateApiKeyto verify the secret exists before opening the modal:const handleCreateApiKey = async (params: OnCreateParams) => { try { - await createApiKey({ + const result = await createApiKey({ ...params, subject, }); card.setError(undefined); - setIsCopyModalOpen(true); + if (result?.secret) { + setIsCopyModalOpen(true); + } else { + card.setError('API key created but secret not available'); + } } catch (err: any) {
🧹 Nitpick comments (1)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (1)
82-97: Signature change correct; consider comprehensive error handling.The removal of
closeCardFnparameter aligns with the new modal flow.However, error handling only covers the 409 conflict case. Other API errors may not set a user-visible error message.
Consider handling generic errors:
} catch (err: any) { if (isClerkAPIResponseError(err)) { if (err.status === 409) { card.setError('API Key name already exists'); + } else { + card.setError(err.errors?.[0]?.message || 'Failed to create API key'); } + } else { + card.setError('An unexpected error occurred'); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx(4 hunks)packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsxpackages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx
🧬 Code graph analysis (1)
packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (3)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
CopyApiKeyModal(24-98)packages/shared/src/types/clerk.ts (1)
CreateAPIKeyParams(1973-1979)packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx (1)
OnCreateParams(23-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
packages/clerk-js/src/ui/components/ApiKeys/CreateApiKeyForm.tsx (2)
30-30: LGTM - Signature simplification aligns with new modal flow.Removing
closeCardFnfrom theonCreatecallback is correct. The form no longer needs to close the card on successful creation since the parent now opens a copy modal instead.
165-172: LGTM - Call site correctly updated.The
onCreatecall correctly passes only the params object, matching the updated signature.packages/clerk-js/src/ui/components/ApiKeys/ApiKeys.tsx (1)
45-49: LGTM - Proper lazy loading.The
CopyApiKeyModalis correctly lazy-loaded with appropriate webpack chunk naming, consistent with the existing modal pattern.
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: 0
🧹 Nitpick comments (3)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (3)
32-36: Simplify by removing unnecessary useFormControl.The
useFormControlhook is not needed here since theClipboardInputis read-only and receives theapiKeySecretvalue directly. The form control adds unnecessary state management overhead without providing validation, transformation, or user interaction capabilities.Apply this diff to simplify:
- const apiKeyField = useFormControl('name', apiKeySecret, { - type: 'text', - label: localizationKeys('formFieldLabel__apiKey'), - isRequired: false, - }); -And update the Form.ControlRow to remove the wrapper:
- <Form.ControlRow - elementDescriptor={descriptors.apiKeysCopyModalInput} - sx={{ flex: 1 }} - > - <Form.CommonInputWrapper {...apiKeyField.props}> - <ClipboardInput - value={apiKeySecret} - readOnly - sx={{ width: '100%' }} - copyIcon={ClipboardOutline} - copiedIcon={Check} - /> - </Form.CommonInputWrapper> - </Form.ControlRow> + <Form.ControlRow + elementDescriptor={descriptors.apiKeysCopyModalInput} + sx={{ flex: 1 }} + > + <ClipboardInput + value={apiKeySecret} + readOnly + sx={{ width: '100%' }} + copyIcon={ClipboardOutline} + copiedIcon={Check} + /> + </Form.ControlRow>And remove the import:
-import { useFormControl } from '@/ui/utils/useFormControl';
38-47: Clarify duplicate copy mechanism and setTimeout delay.Two observations:
Duplicate clipboard management: Both the component-level
useClipboard(line 38) and theClipboardInput(line 80) manage clipboard operations independently. Users can copy via the ClipboardInput's copy button OR the form's submit button, both triggering separate copy actions. Consider whether both copy mechanisms are intentional or if the submit button should only close the modal (since ClipboardInput already provides copy functionality).Unexplained delay: The
setTimeoutwith a 100ms delay before closing the action card (line 44-46) lacks explanation. Document why this delay is necessary (e.g., animation timing, state cleanup) or consider removing it if it's not required.
60-72: Consider adding ARIA attributes for enhanced accessibility.The
role='alertdialog'is appropriate for a modal requiring user action. To further improve accessibility, consider addingaria-labelledbyandaria-describedbyattributes pointing to the form title and hint elements.Example enhancement:
<Card.Root role='alertdialog' + aria-labelledby='copy-api-key-title' + aria-describedby='copy-api-key-hint' elementDescriptor={descriptors.apiKeysCopyModal} >And ensure the FormContainer's header elements have corresponding IDs (may require adjustments to FormContainer component to accept id props).
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
packages/clerk-js/src/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/clerk-js-ui.mdc)
packages/clerk-js/src/ui/**/*.{ts,tsx}: Element descriptors should always be camelCase
Use element descriptors in UI components to enable consistent theming and styling via appearance.elements
Element descriptors should generate unique, stable CSS classes for theming
Element descriptors should handle state classes (e.g., cl-loading, cl-active, cl-error, cl-open) automatically based on component state
Do not render hard-coded values; all user-facing strings must be localized using provided localization methods
Use the useLocalizations hook and localizationKeys utility for all text and error messages
Use the styled system (sx prop, theme tokens, responsive values) for custom component styling
Use useCardState for card-level state, useFormState for form-level state, and useLoadingStatus for loading states
Always use handleError utility for API errors and use translateError for localized error messages
Use useFormControl for form field state, implement proper validation, and handle loading and error states in forms
Use localization keys for all form labels and placeholders
Use element descriptors for consistent styling and follow the theme token system
Use the Card and FormContainer patterns for consistent UI structure
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components
**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components:UserProfile,NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react.mdc)
**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering
Files:
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx
🧬 Code graph analysis (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (5)
packages/clerk-js/src/ui/utils/useFormControl.ts (1)
useFormControl(97-189)packages/clerk-js/src/ui/components/ApiKeys/ApiKeyModal.tsx (1)
ApiKeyModal(36-44)packages/clerk-js/src/ui/elements/FormContainer.tsx (1)
FormContainer(20-61)packages/clerk-js/src/ui/elements/ClipboardInput.tsx (1)
ClipboardInput(13-48)packages/clerk-js/src/ui/elements/FormButtons.tsx (1)
FormButtons(16-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/clerk-js/src/ui/components/ApiKeys/CopyApiKeyModal.tsx (1)
53-99: Well-structured implementation of one-time secret display.The modal correctly implements the PR objective of showing API key secrets only once:
canCloseModal={false}prevents accidental dismissal- Explicit user action (copy and close) required
- Proper localization and theming throughout
- Clean component structure with appropriate hooks
The implementation aligns with security best practices for sensitive credential display.
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: 0
🧹 Nitpick comments (1)
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts (1)
44-46: LGTM! Button click implementation is correct.The scoped selector (
.cl-apiKeysCopyModal .cl-apiKeysCopyModalSubmitButton) ensures the button is clicked within the modal context, which is defensive and correct.Optional: Consider adding explicit return types file-wide.
The coding guidelines recommend explicit return types for public APIs. While this method (and all others in this file) currently rely on type inference, adding return types would improve TypeScript type safety:
clickCopyAndCloseButton: () => { - return page.locator('.cl-apiKeysCopyModal .cl-apiKeysCopyModalSubmitButton').click(); + return page.locator('.cl-apiKeysCopyModal .cl-apiKeysCopyModalSubmitButton').click(); },This would apply to all methods in the file, not just the new ones. Can be deferred to a separate refactoring effort.
As per coding guidelines.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
integration/tests/machine-auth/component.test.ts(5 hunks)packages/testing/src/playwright/unstable/page-objects/apiKeys.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- integration/tests/machine-auth/component.test.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use Prettier for consistent code formatting
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
packages/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
TypeScript is required for all packages
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
packages/**/*.{ts,tsx,d.ts}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Packages should export TypeScript types alongside runtime code
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development.mdc)
Use proper TypeScript error types
**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoidanytype - preferunknownwhen type is uncertain, then narrow with type guards
Useinterfacefor object shapes that might be extended
Usetypefor unions, primitives, and computed types
Preferreadonlyproperties for immutable data structures
Useprivatefor internal implementation details
Useprotectedfor inheritance hierarchies
Usepublicexplicitly for clarity in public APIs
Preferreadonlyfor properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Useconst assertionsfor literal types:as const
Usesatisfiesoperator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports:import type { ... } from ...
Noanytypes without justification
Proper error handling with typed errors
Consistent use ofreadonlyfor immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)
Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.
Files:
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Build Packages
- GitHub Check: Formatting | Dedupe | Changeset
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: semgrep-cloud-platform/scan
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
packages/testing/src/playwright/unstable/page-objects/apiKeys.ts (1)
38-43: LGTM! Modal lifecycle methods follow established patterns.The implementation correctly mirrors the existing revoke modal methods and uses appropriate Playwright selectors and wait strategies.
Description
This PR replaces the persistent key column in the API keys table with a one-time modal that displays the secret immediately after creation.
Screen.Recording.2025-11-03.at.9.24.27.AM.mov
Resolves USER-3698
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change
Summary by CodeRabbit
New Features
Improvements
Tests
Localization