diff --git a/packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx b/packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx
index 9844b8ef814..c13ffd7b427 100644
--- a/packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx
+++ b/packages/ui/src/components/devPrompts/KeylessPrompt/index.tsx
@@ -2,7 +2,7 @@ import { useUser } from '@clerk/shared/react';
// eslint-disable-next-line no-restricted-imports
import { css } from '@emotion/react';
import type { PropsWithChildren } from 'react';
-import { useEffect, useMemo, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import { createPortal } from 'react-dom';
import { Flex, Link } from '../../../customizables';
@@ -28,6 +28,12 @@ const buttonIdentifierPrefix = `--clerk-keyless-prompt`;
const buttonIdentifier = `${buttonIdentifierPrefix}-button`;
const contentIdentifier = `${buttonIdentifierPrefix}-content`;
+// Animation timing constants
+const ANIMATION_DURATION = '200ms';
+const CONTENT_FADE_DURATION = '200ms';
+const CONTENT_FADE_DELAY = '40ms';
+const EASING_CURVE = 'cubic-bezier(0.2, 0, 0, 1)';
+
/**
* If we cannot reconstruct the url properly, then simply fallback to Clerk Dashboard
*/
@@ -39,9 +45,10 @@ function withLastActiveFallback(cb: () => string): string {
}
}
-const KeylessPromptInternal = (_props: KeylessPromptProps) => {
+const _KeylessPromptInternal = (_props: KeylessPromptProps) => {
const { isSignedIn } = useUser();
const [isExpanded, setIsExpanded] = useState(false);
+ const [isAnimating, setIsAnimating] = useState(false);
useEffect(() => {
if (isSignedIn) {
@@ -49,12 +56,22 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
}
}, [isSignedIn]);
+ // Track animation state to prevent interactions during transition
+ useEffect(() => {
+ if (!isAnimating) {
+ return;
+ }
+ const timer = setTimeout(() => setIsAnimating(false), 200);
+ return () => clearTimeout(timer);
+ }, [isAnimating]);
+
const environment = useRevalidateEnvironment();
const claimed = Boolean(environment.authConfig.claimedAt);
const success = typeof _props.onDismiss === 'function' && claimed;
const appName = environment.displayConfig.applicationName;
const isForcedExpanded = claimed || success || isExpanded;
+
const claimUrlToDashboard = useMemo(() => {
if (claimed) {
return _props.copyKeysUrl;
@@ -76,13 +93,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
});
}, [_props.copyKeysUrl]);
- const getKeysUrlFromLastActive = useMemo(() => {
- return withLastActiveFallback(() => {
- const redirectUrlParts = handleDashboardUrlParsing(_props.copyKeysUrl);
- const url = new URL(`${redirectUrlParts.baseDomain}/last-active?path=api-keys`);
- return url.href;
- });
- }, [_props.copyKeysUrl]);
+ const ctaButtonColor = claimed || success ? 'white' : '#fde047';
const mainCTAStyles = css`
${basePromptElementStyles};
@@ -97,7 +108,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.12px;
- color: ${claimed ? 'white' : success ? 'white' : '#fde047'};
+ color: ${ctaButtonColor};
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.32);
white-space: nowrap;
user-select: none;
@@ -111,347 +122,364 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
0px 0px 4px 0px rgba(243, 107, 22, 0) inset;
`;
+ const ctaButtonHoverStyles = claimed
+ ? 'background: #4B4B4B; transition: all 120ms ease-in-out;'
+ : `box-shadow:
+ 0px 0px 6px 0px rgba(253, 224, 71, 0.24) inset,
+ 0px 0px 0px 1px rgba(255, 255, 255, 0.04) inset,
+ 0px 1px 0px 0px rgba(255, 255, 255, 0.04) inset,
+ 0px 0px 0px 1px rgba(0, 0, 0, 0.12),
+ 0px 1.5px 2px 0px rgba(0, 0, 0, 0.48);`;
+
+ function renderStatusIcon() {
+ if (success) {
+ return (
+
- Your application{' '} - - {appName} - {' '} - has been claimed. Configure settings from the{' '} - ({ - color: t.colors.$whiteAlpha600, - textDecoration: 'underline solid', - transition: `${t.transitionTiming.$common} ${t.transitionDuration.$fast}`, - ':hover': { - color: t.colors.$whiteAlpha800, - }, - })} - > - Clerk Dashboard - -
- ) : claimed ? ( -- You claimed this application but haven't set keys in your environment. Get them from the Clerk - Dashboard. -
- ) : isSignedIn ? ( -
-
- You've created your first user! Link this application to your Clerk account to explore the
+
+ Your application{' '}
+
+ {appName}
+ {' '}
+ has been claimed. Configure settings from the{' '}
+ ({
+ color: t.colors.$whiteAlpha600,
+ textDecoration: 'underline solid',
+ transition: `${t.transitionTiming.$common} ${t.transitionDuration.$fast}`,
+ ':hover': {
+ color: t.colors.$whiteAlpha800,
+ },
+ })}
+ >
+ Clerk Dashboard
+
+
+ You claimed this application but haven't set keys in your environment. Get them from the Clerk
Dashboard.
-
-
- Temporary API keys are enabled so you can get started immediately.
- Claim this application to access the Clerk Dashboard where you can manage auth settings and explore
- more Clerk features.
+ ) : isSignedIn ? (
+
+
+ You've created your first user! Link this application to your Clerk account to explore the
+ Dashboard.
+
+ Temporary API keys are enabled so you can get started immediately.
+
+ Claim this application to access the Clerk Dashboard where you can manage auth settings and
+ explore more Clerk features.
+
Temporary API keys are enabled so you can get started immediately.
++ Claim this application to access the Clerk Dashboard where you can manage auth settings and explore + more Clerk features. +
+