@@ -2,10 +2,10 @@ import { useClerk } from '@clerk/shared/react';
22import type { __internal_EnableOrganizationsPromptProps } from '@clerk/shared/types' ;
33// eslint-disable-next-line no-restricted-imports
44import { css } from '@emotion/react' ;
5- import { useMemo , useState } from 'react' ;
5+ import { forwardRef , useMemo , useState } from 'react' ;
66
77import { Modal } from '@/ui/elements/Modal' ;
8- import { InternalThemeProvider } from '@/ui/styledSystem' ;
8+ import { common , InternalThemeProvider } from '@/ui/styledSystem' ;
99
1010import { DevTools } from '../../../../core/resources/DevTools' ;
1111import type { Environment } from '../../../../core/resources/Environment' ;
@@ -32,6 +32,7 @@ const EnableOrganizationsPromptInternal = ({
3232 const clerk = useClerk ( ) ;
3333 const [ isLoading , setIsLoading ] = useState ( false ) ;
3434 const [ isEnabled , setIsEnabled ] = useState ( false ) ;
35+ const [ allowPersonalAccount , setAllowPersonalAccount ] = useState ( false ) ;
3536
3637 // @ts -expect-error - __unstable__environment is not typed
3738 const environment = clerk ?. __unstable__environment as Environment | undefined ;
@@ -70,6 +71,8 @@ const EnableOrganizationsPromptInternal = ({
7071 } ) ;
7172 } ;
7273
74+ const isComponent = ! caller . startsWith ( 'use' ) ;
75+
7376 return (
7477 < Portal >
7578 < Modal
@@ -80,6 +83,7 @@ const EnableOrganizationsPromptInternal = ({
8083 sx = { ( ) => ( {
8184 display : 'flex' ,
8285 flexDirection : 'column' ,
86+ maxWidth : '30rem' ,
8387 } ) }
8488 >
8589 < Flex
@@ -200,7 +204,6 @@ const EnableOrganizationsPromptInternal = ({
200204 direction = 'col'
201205 sx = { t => ( {
202206 gap : t . sizes . $0x5 ,
203- maxWidth : '18.75rem' ,
204207 } ) }
205208 >
206209 { isEnabled ? (
@@ -211,7 +214,7 @@ const EnableOrganizationsPromptInternal = ({
211214 color : # b4b4b4 ;
212215 font-size : 0.8125rem ;
213216 font-weight : 400 ;
214- line-height : 1.23 ;
217+ line-height : 1.3 ;
215218 ` ,
216219 ] }
217220 >
@@ -224,7 +227,7 @@ const EnableOrganizationsPromptInternal = ({
224227 color : # a8a8ff ;
225228 font-size : inherit;
226229 font-weight : 500 ;
227- line-height : 1.5 ;
230+ line-height : 1.3 ;
228231 font-size : 0.8125rem ;
229232 ` ,
230233 ] }
@@ -250,20 +253,22 @@ const EnableOrganizationsPromptInternal = ({
250253 ` ,
251254 ] }
252255 >
253- To use{ ' ' }
256+ To use the { ' ' }
254257 < code
255258 css = { [
256259 basePromptElementStyles ,
257260 css `
261+ font-size : 0.75rem ;
258262 color : white;
259263 font-family : monospace;
260264 line-height : 1.23 ;
261265 ` ,
262266 ] }
263267 >
264- { caller }
265- </ code >
266- , you'll need to enable the Organizations feature for your app first.
268+ { isComponent ? `<${ caller } />` : caller }
269+ </ code > { ' ' }
270+ { isComponent ? 'component' : 'hook' } , you'll need to enable the Organizations feature for your
271+ app first.
267272 </ span >
268273
269274 < a
@@ -287,6 +292,16 @@ const EnableOrganizationsPromptInternal = ({
287292 </ >
288293 ) }
289294 </ Flex >
295+
296+ { ! isEnabled && (
297+ < Flex sx = { t => ( { marginTop : t . sizes . $3 } ) } >
298+ < AllowPersonalAccountSwitch
299+ checked = { allowPersonalAccount }
300+ onChange = { ( ) => setAllowPersonalAccount ( ! allowPersonalAccount ) }
301+ isDisabled = { false }
302+ />
303+ </ Flex >
304+ ) }
290305 </ Flex >
291306
292307 < span
@@ -299,30 +314,22 @@ const EnableOrganizationsPromptInternal = ({
299314 />
300315
301316 < Flex
302- direction = 'col'
303317 justify = 'center'
304318 sx = { t => ( {
305319 padding : `${ t . sizes . $4 } ${ t . sizes . $6 } ` ,
306320 gap : t . sizes . $3 ,
321+ justifyContent : 'flex-end' ,
307322 } ) }
308323 >
309324 { isEnabled ? (
310325 < PromptButton
311- variant = 'outline '
326+ variant = 'solid '
312327 onClick = { ( ) => onSuccess ?.( ) }
313328 >
314329 Continue
315330 </ PromptButton >
316331 ) : (
317332 < >
318- < PromptButton
319- variant = 'solid'
320- onClick = { handleEnableOrganizations }
321- disabled = { isLoading }
322- >
323- Enable Organizations
324- </ PromptButton >
325-
326333 < PromptButton
327334 variant = 'outline'
328335 onClick = { ( ) => {
@@ -332,6 +339,14 @@ const EnableOrganizationsPromptInternal = ({
332339 >
333340 I'll remove it myself
334341 </ PromptButton >
342+
343+ < PromptButton
344+ variant = 'solid'
345+ onClick = { handleEnableOrganizations }
346+ disabled = { isLoading }
347+ >
348+ Enable Organizations
349+ </ PromptButton >
335350 </ >
336351 ) }
337352 </ Flex >
@@ -359,9 +374,7 @@ const mainCTAStyles = css`
359374 dis play: flex;
360375 align- items: center;
361376 justify- content: center;
362- width: 100%;
363377 height: 1.75rem;
364- max- width: 14.625rem;
365378 padding: 0.375rem 0.625rem;
366379 bor der- radius: 0.375rem;
367380 font- size: 0.75rem;
@@ -371,7 +384,6 @@ const mainCTAStyles = css`
371384 text- shadow: 0px 1px 2px rgba(0, 0, 0, 0.32);
372385 white-space: nowrap;
373386 user- select: none;
374- min- width: 100%;
375387 color : white;
376388 transition: all 120ms ease- in- out;
377389
@@ -456,3 +468,121 @@ const PromptButton = ({ variant = 'solid', ...props }: PromptButtonProps) => {
456468 />
457469 ) ;
458470} ;
471+
472+ type AllowPersonalAccountSwitchProps = {
473+ checked : boolean ;
474+ isDisabled : boolean ;
475+ onChange : ( checked : boolean ) => void ;
476+ } ;
477+
478+ const AllowPersonalAccountSwitch = forwardRef < HTMLDivElement , AllowPersonalAccountSwitchProps > (
479+ ( { checked, onChange, isDisabled = false } , ref ) => {
480+ const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
481+ if ( isDisabled ) {
482+ return ;
483+ }
484+
485+ onChange ?.( e . target . checked ) ;
486+ } ;
487+
488+ return (
489+ < Flex
490+ ref = { ref }
491+ direction = 'row'
492+ align = 'center'
493+ as = 'label'
494+ gap = { 2 }
495+ sx = { t => ( {
496+ isolation : 'isolate' ,
497+ width : 'fit-content' ,
498+ '&:has(input:focus-visible) > input + span' : {
499+ ...common . focusRingStyles ( t ) ,
500+ } ,
501+ } ) }
502+ >
503+ { /* The order of the elements is important here for the focus ring to work. The input is visually hidden, so the focus ring is applied to the span. */ }
504+ < input
505+ type = 'checkbox'
506+ role = 'switch'
507+ disabled = { isDisabled }
508+ checked = { checked }
509+ onChange = { handleChange }
510+ tabIndex = { - 1 }
511+ style = { {
512+ ...common . visuallyHidden ( ) ,
513+ } }
514+ />
515+ < Flex
516+ as = 'span'
517+ data-checked = { checked }
518+ sx = { t => ( {
519+ minWidth : t . sizes . $7 ,
520+ alignSelf : 'flex-start' ,
521+ height : t . sizes . $4 ,
522+ alignItems : 'center' ,
523+ position : 'relative' ,
524+ borderColor : '#DBDBE0' ,
525+ backgroundColor : checked ? '#DBDBE0' : t . colors . $primary500 ,
526+ borderRadius : 999 ,
527+ transition : 'background-color 0.2s' ,
528+ opacity : isDisabled ? 0.6 : 1 ,
529+ cursor : isDisabled ? 'not-allowed' : 'pointer' ,
530+ outline : 'none' ,
531+ boxSizing : 'border-box' ,
532+ boxShadow :
533+ '0px 0px 6px 0px rgba(255, 255, 255, 0.04) 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.1)' ,
534+ } ) }
535+ >
536+ < Flex
537+ sx = { t => ( {
538+ position : 'absolute' ,
539+ left : t . sizes . $0x5 ,
540+ width : t . sizes . $3 ,
541+ height : t . sizes . $3 ,
542+ borderRadius : '50%' ,
543+ backgroundColor : 'white' ,
544+ boxShadow : t . shadows . $switchControl ,
545+ transform : `translateX(${ checked ? t . sizes . $3 : 0 } )` ,
546+ transition : 'transform 0.2s' ,
547+ zIndex : 1 ,
548+ } ) }
549+ />
550+ </ Flex >
551+
552+ < Flex
553+ direction = 'col'
554+ gap = { 1 }
555+ >
556+ < p
557+ css = { [
558+ basePromptElementStyles ,
559+ css `
560+ font-size : 0.875rem ;
561+ font-weight : 400 ;
562+ line-height : 1.23 ;
563+ color : white;
564+ ` ,
565+ ] }
566+ >
567+ Allow personal account
568+ </ p >
569+
570+ < span
571+ css = { [
572+ basePromptElementStyles ,
573+ css `
574+ color : # b4b4b4 ;
575+ font-size : 0.8125rem ;
576+ font-weight : 400 ;
577+ line-height : 1.23 ;
578+ ` ,
579+ ] }
580+ >
581+ This is an uncommon setting, meant for applications that sell to both organizations and individual users.
582+ Most B2B applications require users to be part of an organization, and should keep this setting disabled.
583+ </ span >
584+ </ Flex >
585+ </ Flex >
586+ ) ;
587+ } ,
588+ ) ;
0 commit comments