)
}
From ee3f78ff37181b511fa10d55ab156ccee31f7ffc Mon Sep 17 00:00:00 2001
From: Danny White <3104761+dnywh@users.noreply.github.com>
Date: Wed, 26 Aug 2026 17:01:47 +1000
Subject: [PATCH 02/11] fix(studio): hide social sign-in after email sign-up
(#49571)
## What kind of change does this PR introduce?
Bug fix. Resolves
[FE-4264](https://linear.app/supabase/issue/FE-4264/hide-social-sign-in-options-after-email-sign-up).
## What is the current behavior?
After a successful email and password sign-up, GitHub and ChatGPT
sign-in options remain visible even though they do not confirm or link
the new account.
The success state is presented in a bespoke `Alert` with verbose
copywriting.
## What is the new behavior?
The social sign-in options and divider are hidden after email sign-up
succeeds. The email confirmation message and link back to sign in remain
available.
The success state is presented in a standard `success` `Admonition` with
clearer copywriting.
| Before | After |
| --- | --- |
| | |
## To test
1. Open `/sign-up` and complete an email and password sign-up.
2. Confirm the success message is shown without the GitHub, ChatGPT, or
`or` options.
3. Open `/sign-in` and confirm GitHub and ChatGPT remain available
there.
## Summary by CodeRabbit
- **New Features**
- Added shared provider options across sign-in and sign-up flows,
including custom providers, external identity providers, and optional
SSO.
- Added an SSO sign-in button that preserves the current page context.
- After successful email signup, alternative signup options are hidden
and confirmation messaging appears.
- **Bug Fixes**
- Improved signup form spacing, submission state, and animated password
guidance.
- **Tests**
- Added coverage for signup behavior across standard and
focused-provider configurations.
---------
Co-authored-by: Joshen Lim
---
.../interfaces/SignIn/SignInOptions.tsx | 60 +++++++++++
.../interfaces/SignIn/SignInSSOForm.tsx | 16 +++
.../interfaces/SignIn/SignUpForm.tsx | 57 +++++-----
.../misc/__tests__/useInboundBranding.test.ts | 8 ++
apps/studio/hooks/misc/useInboundBranding.ts | 10 +-
apps/studio/pages/sign-in.tsx | 59 ++--------
apps/studio/pages/sign-up.tsx | 86 ++++++---------
apps/studio/tests/pages/sign-up.test.tsx | 101 ++++++++++++++++++
8 files changed, 257 insertions(+), 140 deletions(-)
create mode 100644 apps/studio/components/interfaces/SignIn/SignInOptions.tsx
create mode 100644 apps/studio/tests/pages/sign-up.test.tsx
diff --git a/apps/studio/components/interfaces/SignIn/SignInOptions.tsx b/apps/studio/components/interfaces/SignIn/SignInOptions.tsx
new file mode 100644
index 0000000000000..b2898124ca316
--- /dev/null
+++ b/apps/studio/components/interfaces/SignIn/SignInOptions.tsx
@@ -0,0 +1,60 @@
+import { cn } from 'ui'
+
+import { SignInWithSSOButton } from './SignInSSOForm'
+import { SignInWithCustom } from './SignInWithCustom'
+import { SignInWithExternalProvider } from './SignInWithExternalProvider'
+import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
+import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
+import { type ExternalIdentityProviderConfig } from '@/lib/external-identity-providers'
+
+export const SignInOptions = ({
+ providers,
+ dividerBgClass = 'bg-studio',
+}: {
+ providers: ExternalIdentityProviderConfig[]
+ dividerBgClass?: string
+}) => {
+ const {
+ dashboardAuthSignInWithSso: signInWithSsoEnabled,
+ dashboardAuthSignInWithEmail: signInWithEmailEnabled,
+ } = useIsFeatureEnabled(['dashboard_auth:sign_in_with_sso', 'dashboard_auth:sign_in_with_email'])
+
+ const {
+ dashboardAuthCustomProvider: customProvider,
+ dashboardAuthCustomProviders: customProvidersNew,
+ } = useCustomContent(['dashboard_auth:custom_provider', 'dashboard_auth:custom_providers'])
+
+ // [Joshen] This is just for backward compatibility - singular customProvider needs to be deprecated subsequently
+ // Just need to remove customProvider and rename customProvidersNew to customProviders
+ const customProviders = customProvidersNew ?? (customProvider ? [customProvider] : [])
+
+ const showOrDivider =
+ (providers.length > 0 || signInWithSsoEnabled || customProviders.length > 0) &&
+ signInWithEmailEnabled
+
+ return (
+ <>
+ {Array.isArray(customProviders) &&
+ customProviders.map((providerName: string) => (
+
+ ))}
+
+ {providers.map((provider) => (
+
+ ))}
+
+ {signInWithSsoEnabled && }
+
+ {showOrDivider && (
+
+
+
+
+
+ or
+
+
+ )}
+ >
+ )
+}
diff --git a/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx b/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx
index e27443d13634b..4127113a7d4fd 100644
--- a/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx
+++ b/apps/studio/components/interfaces/SignIn/SignInSSOForm.tsx
@@ -1,6 +1,9 @@
import HCaptcha from '@hcaptcha/react-hcaptcha'
import { zodResolver } from '@hookform/resolvers/zod'
import { useQueryClient } from '@tanstack/react-query'
+import { Lock } from 'lucide-react'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
import { useRef, useState } from 'react'
import { useForm, type SubmitHandler } from 'react-hook-form'
import { toast } from 'sonner'
@@ -8,6 +11,7 @@ import { Button, Form, FormControl, FormField, Input } from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import z from 'zod'
+import { LastSignInWrapper } from './LastSignInWrapper'
import { useLastSignIn } from '@/hooks/misc/useLastSignIn'
import { BASE_PATH } from '@/lib/constants'
import { captureCriticalError } from '@/lib/error-reporting'
@@ -119,3 +123,15 @@ export const SignInSSOForm = () => {
)
}
+
+export const SignInWithSSOButton = () => {
+ const router = useRouter()
+
+ return (
+
+ }>
+ Continue with SSO
+
+
+ )
+}
diff --git a/apps/studio/components/interfaces/SignIn/SignUpForm.tsx b/apps/studio/components/interfaces/SignIn/SignUpForm.tsx
index aa32fb110b08a..14f36b063b6be 100644
--- a/apps/studio/components/interfaces/SignIn/SignUpForm.tsx
+++ b/apps/studio/components/interfaces/SignIn/SignUpForm.tsx
@@ -1,23 +1,14 @@
import HCaptcha from '@hcaptcha/react-hcaptcha'
import { zodResolver } from '@hookform/resolvers/zod'
import { motion } from 'framer-motion'
-import { CheckCircle, Eye, EyeOff } from 'lucide-react'
+import { Eye, EyeOff } from 'lucide-react'
import { useRouter } from 'next/router'
import { parseAsString, useQueryStates } from 'nuqs'
import { useRef, useState } from 'react'
import { SubmitHandler, useForm, useWatch } from 'react-hook-form'
import { toast } from 'sonner'
-import {
- Alert,
- AlertDescription,
- AlertTitle,
- Button,
- cn,
- Form,
- FormControl,
- FormField,
- Input,
-} from 'ui'
+import { Button, cn, Form, FormControl, FormField, Input } from 'ui'
+import { Admonition } from 'ui-patterns/Admonition'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import z from 'zod'
@@ -52,7 +43,7 @@ const schema = z.object({
const formId = 'sign-up-form'
-export const SignUpForm = () => {
+export const SignUpForm = ({ onSuccess }: { onSuccess?: () => void }) => {
const captchaRef = useRef(null)
const [showConditions, setShowConditions] = useState(false)
const [isSubmitted, setIsSubmitted] = useState(false)
@@ -76,6 +67,7 @@ export const SignUpForm = () => {
onSuccess: () => {
toast.success(`Signed up successfully!`)
setIsSubmitted(true)
+ onSuccess?.()
},
onError: (error) => {
setCaptchaToken(null)
@@ -135,22 +127,22 @@ export const SignUpForm = () => {
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.3 }}
- className="absolute top-0 w-full"
+ className="w-full"
>
-
-
- Check your email to confirm
-
- You've successfully signed up. Please check your email to confirm your account before
- signing in to the Supabase dashboard. The confirmation link expires in 10 minutes.
-
-
+
)}