Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/hungry-clouds-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@clerk/clerk-js': minor
"@clerk/types": minor
---

Introducing a development mode warning when in development mode in order to mitigate going to production with development keys.

In case need to deactivate this UI change temporarily to simulate how components will look in production, you can do so by adding the `unsafe_disableDevelopmentModeWarnings` layout appearance prop to `<ClerkProvider>`

Example:

```tsx
<ClerkProvider
appearance={{
layout: {
unsafe_disableDevelopmentModeWarnings: true,
},
}}
/>
```
2 changes: 2 additions & 0 deletions packages/clerk-js/src/core/resources/DisplayConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class DisplayConfig extends BaseResource implements DisplayConfigResource
afterLeaveOrganizationUrl!: string;
afterCreateOrganizationUrl!: string;
googleOneTapClientId?: string;
showDevModeWarning!: boolean;

public constructor(data: DisplayConfigJSON) {
super();
Expand Down Expand Up @@ -80,6 +81,7 @@ export class DisplayConfig extends BaseResource implements DisplayConfigResource
this.afterLeaveOrganizationUrl = data.after_leave_organization_url;
this.afterCreateOrganizationUrl = data.after_create_organization_url;
this.googleOneTapClientId = data.google_one_tap_client_id;
this.showDevModeWarning = data.show_devmode_warning;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ import { useClerk } from '@clerk/shared/react';
import { useCreateOrganizationContext } from '../../contexts';
import { localizationKeys } from '../../customizables';
import { Card, useCardState, withCardStateProvider } from '../../elements';
import { useDevMode } from '../../hooks/useDevMode';
import { CreateOrganizationForm } from './CreateOrganizationForm';

export const CreateOrganizationPage = withCardStateProvider(() => {
const { closeCreateOrganization } = useClerk();

const { mode, navigateAfterCreateOrganization, skipInvitationScreen } = useCreateOrganizationContext();
const card = useCardState();
const { showDevModeNotice } = useDevMode();

return (
<Card.Root sx={t => ({ width: t.sizes.$108 })}>
<Card.Content sx={t => ({ padding: `${t.space.$4} ${t.space.$5} ${t.space.$6}` })}>
<Card.Content
sx={t => ({
padding: `${t.space.$4} ${t.space.$5} ${showDevModeNotice ? t.space.$12 : t.space.$6}`,
})}
>
<Card.Alert>{card.error}</Card.Alert>
<CreateOrganizationForm
skipInvitationScreen={skipInvitationScreen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([
'cardBox',
'card',
'footerItem',
'popoverBox',

'actionCard',

Expand Down
1 change: 1 addition & 0 deletions packages/clerk-js/src/ui/customizables/parseAppearance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const defaultLayout: ParsedLayout = {
termsPageUrl: '',
shimmer: true,
animations: true,
unsafe_disableDevelopmentModeWarnings: false,
};

/**
Expand Down
103 changes: 71 additions & 32 deletions packages/clerk-js/src/ui/elements/Card/CardClerkAndPagesTag.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,91 @@
import React from 'react';

import { useEnvironment } from '../../contexts';
import { Flex, Icon, Link, Text } from '../../customizables';
import { Box, Col, Flex, Icon, Link, Text } from '../../customizables';
import { useDevMode } from '../../hooks/useDevMode';
import { LogoMark } from '../../icons';
import type { PropsOfComponent } from '../../styledSystem';
import type { PropsOfComponent, ThemableCssProp } from '../../styledSystem';
import { DevModeNotice, DevModeOverlay } from '../DevModeNotice';
import { Card } from '.';

export const CardClerkAndPagesTag = React.memo(
React.forwardRef<HTMLDivElement, PropsOfComponent<typeof Flex> & { withFooterPages?: boolean }>((props, ref) => {
const { sx, withFooterPages = false, ...rest } = props;
const { branded } = useEnvironment().displayConfig;
React.forwardRef<
HTMLDivElement,
PropsOfComponent<typeof Flex> & {
withFooterPages?: boolean;
devModeNoticeSx?: ThemableCssProp;
outerSx?: ThemableCssProp;
withDevOverlay?: boolean;
}
>((props, ref) => {
const { sx, outerSx, withFooterPages = false, withDevOverlay = false, devModeNoticeSx, ...rest } = props;
const { displayConfig } = useEnvironment();
const { showDevModeNotice } = useDevMode();

if (!(branded || withFooterPages)) {
if (!(displayConfig.branded || withFooterPages) && !showDevModeNotice) {
return null;
}

return (
<Flex
<Box
sx={[
t => ({
':has(div:only-child)': {
justifyContent: 'center',
},
justifyContent: 'space-between',
{
width: '100%',
padding: `0 ${t.space.$8}`,
}),
sx,
position: 'relative',
isolation: 'isolate',
},
outerSx,
]}
{...rest}
ref={ref}
>
{branded && (
<Flex
gap={1}
align='center'
justify='center'
sx={t => ({ color: t.colors.$colorTextSecondary })}
>
<>
<Text variant='buttonSmall'>Secured by</Text>
<LogoMarkIconLink />
</>
</Flex>
)}
{withDevOverlay && <DevModeOverlay gradient={0} />}
<Col
sx={t => ({
gap: displayConfig.branded || withFooterPages ? t.space.$2 : 0,
marginLeft: 'auto',
marginRight: 'auto',
width: '100%',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1,
position: 'relative',
})}
>
{(displayConfig.branded || withFooterPages) && (
<Flex
sx={[
{
':has(div:only-child)': {
justifyContent: 'center',
},
justifyContent: 'space-between',
width: '100%',
},
sx,
]}
{...rest}
ref={ref}
>
{displayConfig.branded && (
<Flex
gap={1}
align='center'
justify='center'
sx={t => ({ color: t.colors.$colorTextSecondary })}
>
<>
<Text variant='buttonSmall'>Secured by</Text>
<LogoMarkIconLink />
</>
</Flex>
)}

{withFooterPages && <Card.FooterLinks />}
</Flex>
)}

{withFooterPages && <Card.FooterLinks />}
</Flex>
<DevModeNotice sx={devModeNoticeSx} />
</Col>
</Box>
);
}),
);
Expand Down
2 changes: 1 addition & 1 deletion packages/clerk-js/src/ui/elements/Card/CardContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
useLocalizations,
} from '../../customizables';
import { Close } from '../../icons';
import { type PropsOfComponent } from '../../styledSystem';
import type { PropsOfComponent } from '../../styledSystem';
import { useCardState, useFlowMetadata } from '../contexts';
import { IconButton } from '../IconButton';
import { useUnsafeModalContext } from '../Modal';
Expand Down
15 changes: 12 additions & 3 deletions packages/clerk-js/src/ui/elements/Card/CardFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import { useEnvironment } from '../../contexts';
import { descriptors, Flex, Link, localizationKeys, useAppearance } from '../../customizables';
import { useDevMode } from '../../hooks/useDevMode';
import type { InternalTheme, PropsOfComponent } from '../../styledSystem';
import { common, mqu } from '../../styledSystem';
import { colors } from '../../utils';
Expand All @@ -12,12 +13,14 @@ type CardFooterProps = PropsOfComponent<typeof Flex> & {
};
export const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>((props, ref) => {
const { children, isProfileFooter = false, sx, ...rest } = props;
const { branded } = useEnvironment().displayConfig;
const { displayConfig } = useEnvironment();
const { branded } = displayConfig;
const { showDevModeNotice } = useDevMode();
const { helpPageUrl, privacyPageUrl, termsPageUrl } = useAppearance().parsedLayout;
const sponsorOrLinksExist = !!(branded || helpPageUrl || privacyPageUrl || termsPageUrl);
const showSponsorAndLinks = isProfileFooter ? branded : sponsorOrLinksExist;

if (!children && !showSponsorAndLinks) {
if (!children && !(showSponsorAndLinks || showDevModeNotice)) {
return null;
}

Expand Down Expand Up @@ -64,7 +67,13 @@ export const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>((pro
>
{children}

{showSponsorAndLinks && <Card.ClerkAndPagesTag withFooterPages={!isProfileFooter} />}
<Card.ClerkAndPagesTag
withFooterPages={showSponsorAndLinks && !isProfileFooter}
devModeNoticeSx={t => ({
padding: t.space.$none,
})}
withDevOverlay
/>
</Flex>
);
});
Expand Down
55 changes: 55 additions & 0 deletions packages/clerk-js/src/ui/elements/DevModeNotice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { ThemableCssProp } from 'ui/styledSystem';

import { Box, Text } from '../customizables';
import { useDevMode } from '../hooks/useDevMode';

type DevModeOverlayProps = {
gradient?: number;
};

export const DevModeOverlay = (props: DevModeOverlayProps) => {
const { gradient = 60 } = props;
const { showDevModeNotice } = useDevMode();

if (!showDevModeNotice) {
return null;
}

return (
<Box
sx={t => ({
userSelect: 'none',
pointerEvents: 'none',
inset: 0,
position: 'absolute',
background: `repeating-linear-gradient(-45deg,${t.colors.$warningAlpha100},${t.colors.$warningAlpha100} 6px,${t.colors.$warningAlpha150} 6px,${t.colors.$warningAlpha150} 12px)`,
maskImage: `linear-gradient(transparent ${gradient}%, black)`,
})}
/>
);
};

type DevModeNoticeProps = { sx?: ThemableCssProp };
export const DevModeNotice = (props: DevModeNoticeProps) => {
const { sx } = props;
const { showDevModeNotice } = useDevMode();

if (!showDevModeNotice) {
return null;
}

return (
<Text
sx={[
t => ({
color: t.colors.$warning500,
fontWeight: t.fontWeights.$semibold,
padding: t.space.$1x5,
}),
sx,
]}
>
Development mode
</Text>
);
};
9 changes: 6 additions & 3 deletions packages/clerk-js/src/ui/elements/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { animations, common, mqu } from '../styledSystem';
import { colors } from '../utils';
import { Card } from './Card';
import { withFloatingTree } from './contexts';
import { DevModeOverlay } from './DevModeNotice';
import { Popover } from './Popover';

type NavbarContextValue = { isOpen: boolean; open: () => void; close: () => void };
Expand Down Expand Up @@ -140,6 +141,7 @@ const NavbarContainer = (
},
flex: `0 0 ${t.space.$57}`,
width: t.sizes.$57,
position: 'relative',
maxWidth: t.space.$57,
background: common.mergedColorsBackground(
colors.setAlpha(t.colors.$colorBackground, 1),
Expand All @@ -151,6 +153,8 @@ const NavbarContainer = (
justifyContent: 'space-between',
})}
>
<DevModeOverlay />

<Col sx={t => ({ gap: t.space.$6, flex: `0 0 ${t.space.$60}` })}>
<Col
sx={t => ({
Expand All @@ -172,10 +176,9 @@ const NavbarContainer = (
</Col>

<Card.ClerkAndPagesTag
sx={theme => ({
sx={{
width: 'fit-content',
paddingLeft: theme.space.$3,
})}
}}
/>
</Col>
);
Expand Down
25 changes: 15 additions & 10 deletions packages/clerk-js/src/ui/elements/PopoverCard.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React from 'react';

import { useEnvironment } from '../contexts';
import { Col, Flex, Flow, useAppearance } from '../customizables';
import { Col, descriptors, Flex, Flow, useAppearance } from '../customizables';
import type { ElementDescriptor } from '../customizables/elementDescriptors';
import type { PropsOfComponent } from '../styledSystem';
import { animations, common } from '../styledSystem';
import { colors } from '../utils';
import { Card } from '.';

const PopoverCardRoot = React.forwardRef<HTMLDivElement, PropsOfComponent<typeof Card.Content>>((props, ref) => {
const { elementDescriptor, ...rest } = props;
return (
<Flow.Part part='popover'>
<Card.Root
{...props}
elementDescriptor={[descriptors.popoverBox, elementDescriptor as ElementDescriptor]}
{...rest}
ref={ref}
sx={t => ({
width: t.sizes.$94,
Expand Down Expand Up @@ -70,8 +73,6 @@ const PopoverCardFooter = (props: PropsOfComponent<typeof Flex>) => {
),
marginTop: `-${t.space.$2}`,
paddingTop: t.space.$2,
borderBottomLeftRadius: 'inherit',
borderBottomRightRadius: 'inherit',
'&:empty': {
padding: 0,
marginTop: 0,
Expand All @@ -89,12 +90,16 @@ const PopoverCardFooter = (props: PropsOfComponent<typeof Flex>) => {
>
{children}

{shouldShowTagOrLinks && (
<Card.ClerkAndPagesTag
withFooterPages
sx={t => ({ padding: `${t.space.$4} ${t.space.$8}` })}
/>
)}
<Card.ClerkAndPagesTag
outerSx={t => ({
padding: `${t.space.$4} ${t.space.$none}`,
})}
withFooterPages={!!shouldShowTagOrLinks}
devModeNoticeSx={t => ({
padding: t.space.$none,
})}
withDevOverlay
/>
</Col>
);
};
Expand Down
Loading