Skip to content

Commit ba6ca1e

Browse files
committed
extract content
1 parent 3022c61 commit ba6ca1e

1 file changed

Lines changed: 108 additions & 152 deletions

File tree

  • packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt

packages/clerk-js/src/ui/components/devPrompts/KeylessPrompt/index.tsx

Lines changed: 108 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as React from 'react';
66
import { useEffect, useMemo, useState } from 'react';
77
import { createPortal } from 'react-dom';
88

9-
import { Flex, Link } from '../../../customizables';
9+
import { Flex } from '../../../customizables';
1010
import { Portal } from '../../../elements/Portal';
1111
import { InternalThemeProvider } from '../../../styledSystem';
1212
import {
@@ -55,6 +55,10 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
5555
const success = typeof _props.onDismiss === 'function' && claimed;
5656
const appName = environment.displayConfig.applicationName;
5757

58+
// Mock state to 'idle' for now
59+
const currentState: keyof typeof STATES = 'idle';
60+
const content = getContent(currentState);
61+
5862
const isForcedExpanded = claimed || success || isExpanded;
5963
const claimUrlToDashboard = useMemo(() => {
6064
if (claimed) {
@@ -245,10 +249,8 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
245249
)}
246250

247251
<p
248-
data-text='Clerk is in keyless mode'
249-
aria-label={
250-
success ? 'Claim completed' : claimed ? 'Missing environment keys' : 'Clerk is in keyless mode'
251-
}
252+
data-text={content.title}
253+
aria-label={content.ariaLabel}
252254
css={css`
253255
${basePromptElementStyles};
254256
color: #d9d9d9;
@@ -258,7 +260,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
258260
cursor: pointer;
259261
`}
260262
>
261-
{success ? 'Claim completed' : claimed ? 'Missing environment keys' : 'Clerk is in keyless mode'}
263+
{content.title}
262264
</p>
263265
</Flex>
264266

@@ -334,107 +336,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
334336
}
335337
`}
336338
>
337-
{success ? (
338-
<p
339-
css={css`
340-
${basePromptElementStyles};
341-
color: #b4b4b4;
342-
font-size: 0.8125rem;
343-
font-weight: 400;
344-
line-height: 1rem;
345-
`}
346-
>
347-
Your application{' '}
348-
<span
349-
css={css`
350-
${basePromptElementStyles};
351-
display: inline-block;
352-
white-space: nowrap;
353-
overflow: hidden;
354-
text-overflow: ellipsis;
355-
max-width: 8.125rem;
356-
vertical-align: bottom;
357-
font-size: 0.8125rem;
358-
font-weight: 500;
359-
color: #d5d5d5;
360-
`}
361-
>
362-
{appName}
363-
</span>{' '}
364-
has been claimed. Configure settings from the{' '}
365-
<Link
366-
isExternal
367-
aria-label='Go to Dashboard to configure settings'
368-
href={instanceUrlToDashboard}
369-
sx={t => ({
370-
color: t.colors.$whiteAlpha600,
371-
textDecoration: 'underline solid',
372-
transition: `${t.transitionTiming.$common} ${t.transitionDuration.$fast}`,
373-
':hover': {
374-
color: t.colors.$whiteAlpha800,
375-
},
376-
})}
377-
>
378-
Clerk Dashboard
379-
</Link>
380-
</p>
381-
) : claimed ? (
382-
<p
383-
css={css`
384-
${basePromptElementStyles};
385-
color: #b4b4b4;
386-
font-size: 0.8125rem;
387-
font-weight: 400;
388-
line-height: 1rem;
389-
`}
390-
>
391-
You claimed this application but haven&apos;t set keys in your environment. Get them from the Clerk
392-
Dashboard.
393-
</p>
394-
) : isSignedIn ? (
395-
<p
396-
css={css`
397-
${basePromptElementStyles};
398-
color: #b4b4b4;
399-
font-size: 0.8125rem;
400-
font-weight: 400;
401-
line-height: 1rem;
402-
`}
403-
>
404-
<span>
405-
You&apos;ve created your first user! Link this application to your Clerk account to explore the
406-
Dashboard.
407-
</span>
408-
</p>
409-
) : (
410-
<>
411-
<p
412-
css={css`
413-
${basePromptElementStyles};
414-
color: #b4b4b4;
415-
font-size: 0.8125rem;
416-
font-weight: 400;
417-
line-height: 1rem;
418-
text-wrap: pretty;
419-
`}
420-
>
421-
Temporary API keys are enabled so you can get started immediately.
422-
</p>
423-
<p
424-
css={css`
425-
${basePromptElementStyles};
426-
color: #b4b4b4;
427-
font-size: 0.8125rem;
428-
font-weight: 400;
429-
line-height: 1rem;
430-
text-wrap: pretty;
431-
`}
432-
>
433-
Claim this application to access the Clerk Dashboard where you can manage auth settings and explore
434-
more Clerk features.
435-
</p>
436-
</>
437-
)}
339+
{renderDescription(content.description)}
438340
</div>
439341
</div>
440342

@@ -502,7 +404,7 @@ const KeylessPromptInternal = (_props: KeylessPromptProps) => {
502404
}
503405
`}
504406
>
505-
{claimed ? 'Get API keys' : 'Claim application'}
407+
{content.buttonText}
506408
</a>
507409
</Flex>
508410
))}
@@ -572,9 +474,90 @@ const CSS_RESET = css`
572474

573475
const getDuration = (isOpen: boolean) => (isOpen ? DURATION_OPEN : DURATION_CLOSE);
574476

477+
type STATES = 'idle' | 'userCreated' | 'completed';
478+
479+
/**
480+
* Content structure for each state in the KeylessPrompt component.
481+
* Each state maps to UI content including title, description, and button text.
482+
*/
483+
type ContentItem = {
484+
title: string;
485+
description: React.ReactNode | ((...args: any[]) => React.ReactNode);
486+
buttonText: string;
487+
};
488+
489+
const CONTENT: Record<STATES, ContentItem> = {
490+
idle: {
491+
title: 'Configure your application',
492+
description: (
493+
<>
494+
<p>Temporary API keys are enabled so you can get started immediately.</p>
495+
<ul>
496+
{['Add SSO connections (eg. GitHub)', 'Set up B2B authentication', 'Enable MFA'].map(item => (
497+
<li key={item}>{item}</li>
498+
))}
499+
</ul>
500+
<p>Access the dashboard to customize auth settings and explore Clerk features.</p>
501+
</>
502+
),
503+
buttonText: 'Confirgure your application',
504+
},
505+
userCreated: {
506+
title: 'Clerk is in keyless mode',
507+
description: <p>TODO</p>,
508+
buttonText: 'Claim application',
509+
},
510+
completed: {
511+
title: 'Claim completed',
512+
description: (_appName: string, _instanceUrlToDashboard: string) => <p>TODO</p>,
513+
buttonText: 'TODO',
514+
},
515+
};
516+
517+
/**
518+
* Determines the current state based on component props and environment.
519+
* You can modify this logic to match your state management needs.
520+
*/
521+
const getCurrentState = (claimed: boolean, success: boolean, isSignedIn: boolean): STATES => {
522+
if (success) {
523+
return 'completed';
524+
}
525+
if (claimed) {
526+
return 'completed';
527+
}
528+
if (isSignedIn) {
529+
return 'userCreated';
530+
}
531+
return 'idle';
532+
};
533+
534+
/**
535+
* Gets the content object for a given state.
536+
*/
537+
const getContent = (state: STATES) => CONTENT[state];
538+
539+
/**
540+
* Renders the description content, handling both ReactNode and function cases.
541+
* For function descriptions, pass the required parameters.
542+
*/
543+
const renderDescription = (description: ContentItem['description'], ...args: any[]): React.ReactNode => {
544+
if (typeof description === 'function') {
545+
return description(...args);
546+
}
547+
return description;
548+
};
549+
575550
function Keyless() {
576551
const id = React.useId();
552+
553+
const claimed = false;
554+
const success = false;
555+
const isSignedIn = false;
556+
const appName = 'My App';
557+
const instanceUrlToDashboard = 'https://dashboard.clerk.com';
558+
577559
const [isOpen, setIsOpen] = useState(false);
560+
const [currentState, setCurrentState] = useState<STATES>(getCurrentState(claimed, success, isSignedIn));
578561
return (
579562
<div
580563
data-expanded={isOpen}
@@ -673,7 +656,7 @@ function Keyless() {
673656
white-space: nowrap;
674657
`}
675658
>
676-
Configure your application
659+
{getContent(currentState).title}
677660
</span>
678661
<svg
679662
css={css`
@@ -723,60 +706,33 @@ function Keyless() {
723706
padding-block-end: 0.75rem;
724707
opacity: ${isOpen ? 1 : 0};
725708
transition: opacity ${getDuration(isOpen)} ${EASE_BEZIER};
726-
`}
727-
>
728-
<p
729-
css={css`
709+
display: flex;
710+
flex-direction: column;
711+
gap: 0.5rem;
712+
& p {
730713
${CSS_RESET};
731714
color: #b4b4b4;
732715
font-size: 0.8125rem;
733716
font-weight: 400;
734717
line-height: 1rem;
735-
text-box-trim: trim-start;
736-
`}
737-
>
738-
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dignissimos qui laboriosam sit fugiat, ipsam
739-
animi minima neque alias mollitia expedita.
740-
</p>
741-
<ul
742-
css={css`
718+
text-wrap: pretty;
719+
}
720+
& ul {
743721
${CSS_RESET};
744-
margin-top: 0.5rem;
745-
padding-inline-start: 1rem;
746722
list-style: disc;
747-
`}
748-
>
749-
{['Add SSO connections (eg. GitHub)', 'Set up B2B authentication', 'Enable MFA'].map(item => (
750-
<li
751-
key={item}
752-
css={css`
753-
${CSS_RESET};
754-
color: #b4b4b4;
755-
font-size: 0.8125rem;
756-
font-weight: 400;
757-
line-height: 1rem;
758-
&:not(:first-child) {
759-
margin-top: 0.25rem;
760-
}
761-
`}
762-
>
763-
{item}
764-
</li>
765-
))}
766-
</ul>
767-
<p
768-
css={css`
723+
padding-left: 1rem;
724+
}
725+
& li {
769726
${CSS_RESET};
770-
margin-top: 0.5rem;
771727
color: #b4b4b4;
772728
font-size: 0.8125rem;
773729
font-weight: 400;
774730
line-height: 1rem;
775-
`}
776-
>
777-
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dignissimos qui laboriosam sit fugiat, ipsam
778-
animi minima neque alias mollitia expedita.
779-
</p>
731+
text-wrap: pretty;
732+
}
733+
`}
734+
>
735+
{renderDescription(getContent(currentState).description, appName, instanceUrlToDashboard)}
780736

781737
<a
782738
href='https://clerk.com/dashboard'
@@ -819,7 +775,7 @@ function Keyless() {
819775
}
820776
`}
821777
>
822-
Configure your application
778+
{getContent(currentState).buttonText}
823779
</a>
824780
</div>
825781
</div>

0 commit comments

Comments
 (0)