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
3 changes: 3 additions & 0 deletions apps/sim/app/(auth)/components/auth-button-classes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/** Shared className for primary auth form submit buttons across all auth pages. */
export const AUTH_SUBMIT_BTN =
'inline-flex h-[32px] w-full items-center justify-center gap-2 rounded-[5px] border border-white bg-white px-2.5 font-[430] font-season text-black text-sm transition-colors hover:border-[var(--border-1)] hover:bg-[var(--border-1)] disabled:cursor-not-allowed disabled:opacity-50' as const
102 changes: 0 additions & 102 deletions apps/sim/app/(auth)/components/branded-button.tsx

This file was deleted.

14 changes: 2 additions & 12 deletions apps/sim/app/(auth)/components/sso-login-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,18 @@ import { useRouter } from 'next/navigation'
import { Button } from '@/components/emcn'
import { getEnv, isTruthy } from '@/lib/core/config/env'
import { cn } from '@/lib/core/utils/cn'
import { AUTH_SUBMIT_BTN } from '@/app/(auth)/components/auth-button-classes'

interface SSOLoginButtonProps {
callbackURL?: string
className?: string
// Visual variant for button styling and placement contexts
// - 'primary' matches the main auth action button style
// - 'outline' matches social provider buttons
variant?: 'primary' | 'outline'
// Optional class used when variant is primary to match brand/gradient
primaryClassName?: string
}

export function SSOLoginButton({
callbackURL,
className,
variant = 'outline',
primaryClassName,
}: SSOLoginButtonProps) {
const router = useRouter()

Expand All @@ -33,19 +28,14 @@ export function SSOLoginButton({
router.push(ssoUrl)
}

const primaryBtnClasses = cn(
primaryClassName || 'branded-button-gradient',
'flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-base text-white transition-all duration-200'
)

const outlineBtnClasses = cn('w-full rounded-[10px]')

return (
<Button
type='button'
onClick={handleSSOClick}
variant={variant === 'outline' ? 'outline' : undefined}
className={cn(variant === 'outline' ? outlineBtnClasses : primaryBtnClasses, className)}
className={cn(variant === 'outline' ? outlineBtnClasses : AUTH_SUBMIT_BTN, className)}
>
Sign in with SSO
</Button>
Expand Down
55 changes: 24 additions & 31 deletions apps/sim/app/(auth)/login/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useRef, useState } from 'react'
import { createLogger } from '@sim/logger'
import { Eye, EyeOff } from 'lucide-react'
import { Eye, EyeOff, Loader2 } from 'lucide-react'
import Link from 'next/link'
import { useRouter, useSearchParams } from 'next/navigation'
import {
Expand All @@ -20,10 +20,9 @@ import { validateCallbackUrl } from '@/lib/core/security/input-validation'
import { cn } from '@/lib/core/utils/cn'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { quickValidateEmail } from '@/lib/messaging/email/validation'
import { BrandedButton } from '@/app/(auth)/components/branded-button'
import { AUTH_SUBMIT_BTN } from '@/app/(auth)/components/auth-button-classes'
import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons'
import { SSOLoginButton } from '@/app/(auth)/components/sso-login-button'
import { useBrandedButtonClass } from '@/hooks/use-branded-button-class'

const logger = createLogger('LoginForm')

Expand Down Expand Up @@ -87,8 +86,6 @@ export default function LoginPage({
const [passwordErrors, setPasswordErrors] = useState<string[]>([])
const [showValidationError, setShowValidationError] = useState(false)
const [formError, setFormError] = useState<string | null>(null)
const buttonClass = useBrandedButtonClass()

const callbackUrlParam = searchParams?.get('callbackUrl')
const isValidCallbackUrl = callbackUrlParam ? validateCallbackUrl(callbackUrlParam) : false
const invalidCallbackRef = useRef(false)
Expand Down Expand Up @@ -353,11 +350,7 @@ export default function LoginPage({
{/* SSO Login Button (primary top-only when it is the only method) */}
{showTopSSO && (
<div className='mt-8'>
<SSOLoginButton
callbackURL={callbackUrl}
variant='primary'
primaryClassName={buttonClass}
/>
<SSOLoginButton callbackURL={callbackUrl} variant='primary' />
</div>
)}

Expand Down Expand Up @@ -454,14 +447,16 @@ export default function LoginPage({
</div>
)}

<BrandedButton
type='submit'
disabled={isLoading}
loading={isLoading}
loadingText='Signing in'
>
Sign in
</BrandedButton>
<button type='submit' disabled={isLoading} className={AUTH_SUBMIT_BTN}>
{isLoading ? (
<span className='flex items-center gap-2'>
<Loader2 className='h-4 w-4 animate-spin' />
Signing in...
</span>
) : (
'Sign in'
)}
</button>
</form>
)}

Expand All @@ -488,11 +483,7 @@ export default function LoginPage({
callbackURL={callbackUrl}
>
{ssoEnabled && !hasOnlySSO && (
<SSOLoginButton
callbackURL={callbackUrl}
variant='outline'
primaryClassName={buttonClass}
/>
<SSOLoginButton callbackURL={callbackUrl} variant='outline' />
)}
</SocialLoginButtons>
</div>
Expand Down Expand Up @@ -571,14 +562,16 @@ export default function LoginPage({
<p>{resetStatus.message}</p>
</div>
)}
<BrandedButton
type='submit'
disabled={isSubmittingReset}
loading={isSubmittingReset}
loadingText='Sending'
>
Send Reset Link
</BrandedButton>
<button type='submit' disabled={isSubmittingReset} className={AUTH_SUBMIT_BTN}>
{isSubmittingReset ? (
<span className='flex items-center gap-2'>
<Loader2 className='h-4 w-4 animate-spin' />
Sending...
</span>
) : (
'Send Reset Link'
)}
</button>
</div>
</form>
</ModalBody>
Expand Down
29 changes: 18 additions & 11 deletions apps/sim/app/(auth)/oauth/consent/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client'

import { useCallback, useEffect, useState } from 'react'
import { ArrowLeftRight } from 'lucide-react'
import { ArrowLeftRight, Loader2 } from 'lucide-react'
import Image from 'next/image'
import { useRouter, useSearchParams } from 'next/navigation'
import { Button } from '@/components/emcn'
import { signOut, useSession } from '@/lib/auth/auth-client'
import { BrandedButton } from '@/app/(auth)/components/branded-button'
import { AUTH_SUBMIT_BTN } from '@/app/(auth)/components/auth-button-classes'

const SCOPE_DESCRIPTIONS: Record<string, string> = {
openid: 'Verify your identity',
Expand Down Expand Up @@ -150,7 +150,9 @@ export default function OAuthConsentPage() {
</p>
</div>
<div className='mt-8 w-full max-w-[410px] space-y-3'>
<BrandedButton onClick={() => router.push('/')}>Return to Home</BrandedButton>
<button onClick={() => router.push('/')} className={AUTH_SUBMIT_BTN}>
Return to Home
</button>
</div>
</div>
)
Expand Down Expand Up @@ -230,7 +232,7 @@ export default function OAuthConsentPage() {

{scopes.length > 0 && (
<div className='mt-5 w-full max-w-[410px]'>
<div className='rounded-lg border p-4'>
<div className='rounded-lg border border-[var(--landing-bg-elevated)] p-4'>
<p className='mb-3 font-medium text-sm'>This will allow the application to:</p>
<ul className='space-y-2'>
{scopes.map((s) => (
Expand All @@ -257,15 +259,20 @@ export default function OAuthConsentPage() {
>
Deny
</Button>
<BrandedButton
fullWidth
showArrow={false}
loading={submitting}
loadingText='Authorizing'
<button
onClick={() => handleConsent(true)}
disabled={submitting}
className={AUTH_SUBMIT_BTN}
>
Allow
</BrandedButton>
{submitting ? (
<span className='flex items-center gap-2'>
<Loader2 className='h-4 w-4 animate-spin' />
Authorizing...
</span>
) : (
'Allow'
)}
</button>
</div>
</div>
)
Expand Down
40 changes: 22 additions & 18 deletions apps/sim/app/(auth)/reset-password/reset-password-form.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use client'

import { useState } from 'react'
import { Eye, EyeOff } from 'lucide-react'
import { Eye, EyeOff, Loader2 } from 'lucide-react'
import { Input, Label } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import { BrandedButton } from '@/app/(auth)/components/branded-button'
import { AUTH_SUBMIT_BTN } from '@/app/(auth)/components/auth-button-classes'

interface RequestResetFormProps {
email: string
Expand Down Expand Up @@ -64,14 +64,16 @@ export function RequestResetForm({
)}
</div>

<BrandedButton
type='submit'
disabled={isSubmitting}
loading={isSubmitting}
loadingText='Sending'
>
Send Reset Link
</BrandedButton>
<button type='submit' disabled={isSubmitting} className={AUTH_SUBMIT_BTN}>
{isSubmitting ? (
<span className='flex items-center gap-2'>
<Loader2 className='h-4 w-4 animate-spin' />
Sending...
</span>
) : (
'Send Reset Link'
)}
</button>
</form>
)
}
Expand Down Expand Up @@ -219,14 +221,16 @@ export function SetNewPasswordForm({
)}
</div>

<BrandedButton
type='submit'
disabled={isSubmitting || !token}
loading={isSubmitting}
loadingText='Resetting'
>
Reset Password
</BrandedButton>
<button type='submit' disabled={isSubmitting || !token} className={AUTH_SUBMIT_BTN}>
{isSubmitting ? (
<span className='flex items-center gap-2'>
<Loader2 className='h-4 w-4 animate-spin' />
Resetting...
</span>
) : (
'Reset Password'
)}
</button>
</form>
)
}
Loading
Loading