diff --git a/packages/ui/src/components/sign-in/sign-in.tsx b/packages/ui/src/components/sign-in/sign-in.tsx
index e47313ad243..d2921eb2058 100644
--- a/packages/ui/src/components/sign-in/sign-in.tsx
+++ b/packages/ui/src/components/sign-in/sign-in.tsx
@@ -2,6 +2,7 @@ import { Root as SignInRoot } from '@clerk/elements/sign-in';
import * as React from 'react';
import { GetHelpContext } from '~/components/sign-in/hooks/use-get-help';
+import { SignInChooseSession } from '~/components/sign-in/steps/choose-session';
import { SignInChooseStrategy } from '~/components/sign-in/steps/choose-strategy';
import { SignInForgotPassword } from '~/components/sign-in/steps/forgot-password';
import { SignInGetHelp } from '~/components/sign-in/steps/get-help';
@@ -10,8 +11,6 @@ import { SignInStart } from '~/components/sign-in/steps/start';
import { SignInVerifications } from '~/components/sign-in/steps/verifications';
import { type Appearance, AppearanceProvider, useAppearance } from '~/contexts';
-import { SignInChooseSession } from './steps/choose-session';
-
/**
* Implementation Details:
*
diff --git a/packages/ui/src/components/sign-in/steps/choose-session.tsx b/packages/ui/src/components/sign-in/steps/choose-session.tsx
index f22673ef800..833b82aa25c 100644
--- a/packages/ui/src/components/sign-in/steps/choose-session.tsx
+++ b/packages/ui/src/components/sign-in/steps/choose-session.tsx
@@ -4,9 +4,8 @@ import { cva } from 'cva';
import { Button } from 'react-aria-components';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
-import { useDisplayConfig } from '~/hooks/use-display-config';
import { useLocalizations } from '~/hooks/use-localizations';
import * as Card from '~/primitives/card';
import * as Icon from '~/primitives/icon';
@@ -60,16 +59,8 @@ const sessionAction = cva({
export function SignInChooseSession() {
const { signOut } = useClerk();
const { t } = useLocalizations();
- const { layout } = useAppearance().parsedAppearance;
const isDev = useDevModeWarning();
- const { branded } = useDisplayConfig();
-
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { footerProps } = useCard();
return (
@@ -160,7 +151,7 @@ export function SignInChooseSession() {
-
+
);
diff --git a/packages/ui/src/components/sign-in/steps/start.tsx b/packages/ui/src/components/sign-in/steps/start.tsx
index ab12c3b51db..c34b25472c6 100644
--- a/packages/ui/src/components/sign-in/steps/start.tsx
+++ b/packages/ui/src/components/sign-in/steps/start.tsx
@@ -11,8 +11,8 @@ import { PhoneNumberField } from '~/common/phone-number-field';
import { PhoneNumberOrUsernameField } from '~/common/phone-number-or-username-field';
import { UsernameField } from '~/common/username-field';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
import { useAttributes } from '~/hooks/use-attributes';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
import { useDisplayConfig } from '~/hooks/use-display-config';
import { useEnabledConnections } from '~/hooks/use-enabled-connections';
@@ -26,27 +26,16 @@ import { Separator } from '~/primitives/separator';
export function SignInStart() {
const enabledConnections = useEnabledConnections();
const { t } = useLocalizations();
- const { layout } = useAppearance().parsedAppearance;
const { enabled: usernameEnabled } = useAttributes('username');
const { enabled: phoneNumberEnabled } = useAttributes('phone_number');
const { enabled: emailAddressEnabled } = useAttributes('email_address');
const { enabled: passkeyEnabled } = useAttributes('passkey');
- const { applicationName, branded, logoImageUrl, homeUrl } = useDisplayConfig();
+ const { applicationName } = useDisplayConfig();
const hasConnection = enabledConnections.length > 0;
const hasIdentifier = emailAddressEnabled || usernameEnabled || phoneNumberEnabled;
const isDev = useDevModeWarning();
- const cardLogoProps = {
- href: layout?.logoLinkUrl || homeUrl,
- src: layout?.logoImageUrl || logoImageUrl,
- alt: applicationName,
- };
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { logoProps, footerProps } = useCard();
return (
@@ -56,7 +45,7 @@ export function SignInStart() {
-
+
{t('signIn.start.title', { applicationName })}
{t('signIn.start.subtitle', { applicationName })}
@@ -180,7 +169,7 @@ export function SignInStart() {
-
+
{t('signIn.start.actionText')}{' '}
diff --git a/packages/ui/src/components/sign-in/steps/verifications.tsx b/packages/ui/src/components/sign-in/steps/verifications.tsx
index 314007c8f92..01a49f652c5 100644
--- a/packages/ui/src/components/sign-in/steps/verifications.tsx
+++ b/packages/ui/src/components/sign-in/steps/verifications.tsx
@@ -6,7 +6,7 @@ import { GlobalError } from '~/common/global-error';
import { OTPField } from '~/common/otp-field';
import { PasswordField } from '~/common/password-field';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
import { useDisplayConfig } from '~/hooks/use-display-config';
import { useLocalizations } from '~/hooks/use-localizations';
@@ -19,22 +19,11 @@ import { formatSafeIdentifier } from '~/utils/format-safe-identifier';
export function SignInVerifications() {
const { t } = useLocalizations();
- const { layout } = useAppearance().parsedAppearance;
- const { applicationName, branded, logoImageUrl, homeUrl } = useDisplayConfig();
+ const { applicationName } = useDisplayConfig();
const isDev = useDevModeWarning();
const isPasswordResetSupported = useResetPasswordFactor();
- const cardLogoProps = {
- href: layout?.logoLinkUrl || homeUrl,
- src: layout?.logoImageUrl || logoImageUrl,
- alt: applicationName,
- };
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { logoProps, footerProps } = useCard();
return (
@@ -45,7 +34,7 @@ export function SignInVerifications() {
-
+
{t('signIn.password.title')}
{t('signIn.password.subtitle')}
@@ -122,7 +111,7 @@ export function SignInVerifications() {
-
+
{t('signIn.passkey.title')}
{t('signIn.passkey.subtitle')}
@@ -176,7 +165,7 @@ export function SignInVerifications() {
-
+
{t('signIn.backupCodeMfa.title')}
{t('signIn.backupCodeMfa.subtitle')}
@@ -222,7 +211,7 @@ export function SignInVerifications() {
-
+
{t('signIn.emailCode.title')}
{t('signIn.emailCode.subtitle', { applicationName })}
@@ -301,7 +290,7 @@ export function SignInVerifications() {
-
+
{t('signIn.phoneCode.title')}
{t('signIn.phoneCode.subtitle', { applicationName })}
@@ -381,7 +370,7 @@ export function SignInVerifications() {
-
+
{t('signIn.emailLink.title')}
{t('signIn.emailLink.formSubtitle', { applicationName })}
@@ -492,7 +481,7 @@ export function SignInVerifications() {
-
+
{t('signIn.totpMfa.formTitle')}
{t('signIn.totpMfa.subtitle', { applicationName })}
@@ -534,7 +523,7 @@ export function SignInVerifications() {
-
+
);
diff --git a/packages/ui/src/components/sign-up/steps/continue.tsx b/packages/ui/src/components/sign-up/steps/continue.tsx
index 05044b45f53..54380ff92a0 100644
--- a/packages/ui/src/components/sign-up/steps/continue.tsx
+++ b/packages/ui/src/components/sign-up/steps/continue.tsx
@@ -9,10 +9,9 @@ import { PasswordField } from '~/common/password-field';
import { PhoneNumberField } from '~/common/phone-number-field';
import { UsernameField } from '~/common/username-field';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
import { useAttributes } from '~/hooks/use-attributes';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
-import { useDisplayConfig } from '~/hooks/use-display-config';
import { useLocalizations } from '~/hooks/use-localizations';
import { Button } from '~/primitives/button';
import * as Card from '~/primitives/card';
@@ -20,25 +19,13 @@ import * as Icon from '~/primitives/icon';
export function SignUpContinue() {
const { t } = useLocalizations();
- const { layout } = useAppearance().parsedAppearance;
const { enabled: firstNameEnabled, required: firstNameRequired } = useAttributes('first_name');
const { enabled: lastNameEnabled, required: lastNameRequired } = useAttributes('last_name');
const { enabled: usernameEnabled, required: usernameRequired } = useAttributes('username');
const { enabled: phoneNumberEnabled, required: phoneNumberRequired } = useAttributes('phone_number');
const { enabled: passwordEnabled, required: passwordRequired } = useAttributes('password');
- const { branded, applicationName, homeUrl, logoImageUrl } = useDisplayConfig();
const isDev = useDevModeWarning();
- const cardLogoProps = {
- href: layout?.logoLinkUrl || homeUrl,
- src: layout?.logoImageUrl || logoImageUrl,
- alt: applicationName,
- };
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { logoProps, footerProps } = useCard();
return (
@@ -48,7 +35,7 @@ export function SignUpContinue() {
-
+
{t('signUp.continue.title')}
{t('signUp.continue.subtitle')}
@@ -117,7 +104,7 @@ export function SignUpContinue() {
-
+
{t('signUp.continue.actionText')}{' '}
diff --git a/packages/ui/src/components/sign-up/steps/start.tsx b/packages/ui/src/components/sign-up/steps/start.tsx
index 68042c7009e..f2f4693fabb 100644
--- a/packages/ui/src/components/sign-up/steps/start.tsx
+++ b/packages/ui/src/components/sign-up/steps/start.tsx
@@ -12,8 +12,8 @@ import { PasswordField } from '~/common/password-field';
import { PhoneNumberField } from '~/common/phone-number-field';
import { UsernameField } from '~/common/username-field';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
import { useAttributes } from '~/hooks/use-attributes';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
import { useDisplayConfig } from '~/hooks/use-display-config';
import { useEnabledConnections } from '~/hooks/use-enabled-connections';
@@ -28,7 +28,6 @@ export function SignUpStart() {
const clerk = useClerk();
const enabledConnections = useEnabledConnections();
const { userSettings } = useEnvironment();
- const { layout } = useAppearance().parsedAppearance;
const { t } = useLocalizations();
const { enabled: firstNameEnabled, required: firstNameRequired } = useAttributes('first_name');
const { enabled: lastNameEnabled, required: lastNameRequired } = useAttributes('last_name');
@@ -36,22 +35,12 @@ export function SignUpStart() {
const { enabled: phoneNumberEnabled, required: phoneNumberRequired } = useAttributes('phone_number');
const { enabled: emailAddressEnabled, required: emailAddressRequired } = useAttributes('email_address');
const { enabled: passwordEnabled, required: passwordRequired } = useAttributes('password');
- const { applicationName, branded, homeUrl, logoImageUrl } = useDisplayConfig();
+ const { applicationName } = useDisplayConfig();
const hasConnection = enabledConnections.length > 0;
const hasIdentifier = emailAddressEnabled || usernameEnabled || phoneNumberEnabled;
const isDev = useDevModeWarning();
- const cardLogoProps = {
- href: layout?.logoLinkUrl || homeUrl,
- src: layout?.logoImageUrl || logoImageUrl,
- alt: applicationName,
- };
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { logoProps, footerProps } = useCard();
return (
@@ -61,7 +50,7 @@ export function SignUpStart() {
-
+
{t('signUp.start.title')}
{t('signUp.start.subtitle', {
@@ -154,7 +143,7 @@ export function SignUpStart() {
) : null}
-
+
{t('signUp.start.actionText')}{' '}
diff --git a/packages/ui/src/components/sign-up/steps/verifications.tsx b/packages/ui/src/components/sign-up/steps/verifications.tsx
index 760cdab539c..9498ae1d33e 100644
--- a/packages/ui/src/components/sign-up/steps/verifications.tsx
+++ b/packages/ui/src/components/sign-up/steps/verifications.tsx
@@ -5,7 +5,7 @@ import * as SignUp from '@clerk/elements/sign-up';
import { GlobalError } from '~/common/global-error';
import { OTPField } from '~/common/otp-field';
import { LOCALIZATION_NEEDED } from '~/constants/localizations';
-import { useAppearance } from '~/contexts';
+import { useCard } from '~/hooks/use-card';
import { useDevModeWarning } from '~/hooks/use-dev-mode-warning';
import { useDisplayConfig } from '~/hooks/use-display-config';
import { useLocalizations } from '~/hooks/use-localizations';
@@ -46,21 +46,10 @@ function SignUpIdentifier({ emailAddress, phoneNumber }: Identifier) {
export function SignUpVerifications() {
const { t } = useLocalizations();
- const { layout } = useAppearance().parsedAppearance;
- const { branded, applicationName, homeUrl, logoImageUrl } = useDisplayConfig();
+ const { applicationName } = useDisplayConfig();
const isDev = useDevModeWarning();
- const cardLogoProps = {
- href: layout?.logoLinkUrl || homeUrl,
- src: layout?.logoImageUrl || logoImageUrl,
- alt: applicationName,
- };
- const cardFooterProps = {
- branded,
- helpPageUrl: layout?.helpPageUrl,
- privacyPageUrl: layout?.privacyPageUrl,
- termsPageUrl: layout?.termsPageUrl,
- };
+ const { logoProps, footerProps } = useCard();
return (
@@ -71,7 +60,7 @@ export function SignUpVerifications() {
-
+
{t('signUp.phoneCode.title')}
{t('signUp.phoneCode.subtitle')}
@@ -143,7 +132,7 @@ export function SignUpVerifications() {
-
+
{t('signUp.emailCode.title')}
{t('signUp.emailCode.subtitle')}
@@ -215,7 +204,7 @@ export function SignUpVerifications() {
-
+
{t('signUp.emailLink.title')}
{t('signUp.emailLink.subtitle', {
@@ -265,7 +254,7 @@ export function SignUpVerifications() {
-
+
);
diff --git a/packages/ui/src/hooks/use-card.ts b/packages/ui/src/hooks/use-card.ts
new file mode 100644
index 00000000000..4db9adc6f20
--- /dev/null
+++ b/packages/ui/src/hooks/use-card.ts
@@ -0,0 +1,47 @@
+import { useAppearance } from '~/contexts';
+
+import { useDisplayConfig } from './use-display-config';
+
+/**
+ * Access card rendering values for the `` and ``
+ * based on the display config and parsed appearance.
+ *
+ * @example
+ * ```tsx
+ * import { useCard } from './use-card';
+ *
+ * function MyCardComponent() {
+ * const { logoProps, footerProps } = useCard();
+ *
+ * return (
+ *
+ *
+ *
+ *
+ * );
+ * }
+ * ```
+ */
+
+export function useCard() {
+ const { layout } = useAppearance().parsedAppearance;
+ const { applicationName, branded, logoImageUrl, homeUrl } = useDisplayConfig();
+
+ const logoProps = {
+ href: layout?.logoLinkUrl || homeUrl,
+ src: layout?.logoImageUrl || logoImageUrl,
+ alt: applicationName,
+ };
+
+ const footerProps = {
+ branded,
+ helpPageUrl: layout?.helpPageUrl,
+ privacyPageUrl: layout?.privacyPageUrl,
+ termsPageUrl: layout?.termsPageUrl,
+ };
+
+ return {
+ logoProps,
+ footerProps,
+ };
+}
diff --git a/packages/ui/theme-builder/public/clerk-logo-dark-accent.svg b/packages/ui/theme-builder/public/clerk-logo-dark-accent.svg
new file mode 100644
index 00000000000..294837b0965
--- /dev/null
+++ b/packages/ui/theme-builder/public/clerk-logo-dark-accent.svg
@@ -0,0 +1,6 @@
+