Skip to content

Commit 0725c98

Browse files
committed
improvement(ui): align all public pages with dark landing theme and improve whitelabeling
1 parent c191f15 commit 0725c98

File tree

70 files changed

+959
-1357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+959
-1357
lines changed

apps/sim/app/(auth)/auth-layout-client.tsx

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,22 @@
22

33
import { useEffect } from 'react'
44
import AuthBackground from '@/app/(auth)/components/auth-background'
5-
import Nav from '@/app/(landing)/components/nav/nav'
6-
7-
function isColorDark(hexColor: string): boolean {
8-
const hex = hexColor.replace('#', '')
9-
const r = Number.parseInt(hex.substr(0, 2), 16)
10-
const g = Number.parseInt(hex.substr(2, 2), 16)
11-
const b = Number.parseInt(hex.substr(4, 2), 16)
12-
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
13-
return luminance < 0.5
14-
}
5+
import Navbar from '@/app/(home)/components/navbar/navbar'
156

167
export default function AuthLayoutClient({ children }: { children: React.ReactNode }) {
178
useEffect(() => {
18-
const rootStyle = getComputedStyle(document.documentElement)
19-
const brandBackground = rootStyle.getPropertyValue('--brand-background-hex').trim()
20-
21-
if (brandBackground && isColorDark(brandBackground)) {
22-
document.body.classList.add('auth-dark-bg')
23-
} else {
24-
document.body.classList.remove('auth-dark-bg')
9+
document.documentElement.classList.add('dark')
10+
return () => {
11+
document.documentElement.classList.remove('dark')
2512
}
2613
}, [])
14+
2715
return (
28-
<AuthBackground>
29-
<main className='relative flex min-h-screen flex-col text-foreground'>
30-
<Nav hideAuthButtons={true} variant='auth' />
16+
<AuthBackground className='dark font-[430] font-season'>
17+
<main className='relative flex min-h-full flex-col text-[#ECECEC]'>
18+
<header className='shrink-0 bg-[#1C1C1C]'>
19+
<Navbar logoOnly />
20+
</header>
3121
<div className='relative z-30 flex flex-1 items-center justify-center px-4 pb-24'>
3222
<div className='w-full max-w-lg px-4'>{children}</div>
3323
</div>
Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,93 @@
11
export default function AuthBackgroundSVG() {
22
return (
3-
<svg
4-
aria-hidden='true'
5-
className='pointer-events-none fixed inset-0 h-full w-full'
6-
style={{ zIndex: 5 }}
7-
viewBox='0 0 1880 960'
8-
fill='none'
9-
xmlns='http://www.w3.org/2000/svg'
10-
preserveAspectRatio='xMidYMid slice'
11-
>
12-
{/* Right side paths - extended to connect */}
13-
<path
14-
d='M1393.53 42.8889C1545.99 173.087 1688.28 339.75 1878.44 817.6'
15-
stroke='#E7E4EF'
16-
strokeWidth='2'
17-
/>
18-
<path d='M1624.21 960L1625.78 0' stroke='#E7E4EF' strokeWidth='2' />
19-
<path d='M1832.67 715.81L1880 716.031' stroke='#E7E4EF' strokeWidth='2' />
20-
<path d='M1393.4 40V0' stroke='#E7E4EF' strokeWidth='2' />
21-
<circle cx='1393.03' cy='40.0186' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
22-
<circle cx='1625.28' cy='303.147' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
23-
<circle cx='1837.37' cy='715.81' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
3+
<>
4+
{/* Top-left card outline */}
5+
<div
6+
aria-hidden='true'
7+
className='pointer-events-none absolute top-[-3vw] left-[-10vw] z-[5] aspect-[344/328] w-[38vw]'
8+
>
9+
<svg
10+
viewBox='0 0 344 328'
11+
fill='none'
12+
xmlns='http://www.w3.org/2000/svg'
13+
preserveAspectRatio='xMidYMid meet'
14+
className='h-full w-full'
15+
>
16+
<path
17+
d='M322.641 326.586L335.508 326.586C339.926 326.586 343.508 323.004 343.508 318.586V153.613C343.508 149.195 339.926 145.613 335.508 145.613H228.282C223.864 145.613 220.282 142.031 220.282 137.613V-50H190.282V137.613C190.282 142.031 186.7 145.613 182.282 145.613H-157V318.586C-157 323.004 -153.418 326.586 -149 326.586H322.641Z'
18+
fill='#1C1C1C'
19+
stroke='#323232'
20+
strokeOpacity='0.4'
21+
strokeWidth='1'
22+
/>
23+
</svg>
24+
</div>
2425

25-
{/* Left side paths - extended to connect */}
26-
<path
27-
d='M160 157.764C319.811 136.451 417.278 102.619 552.39 0'
28-
stroke='#E7E4EF'
29-
strokeWidth='2'
30-
/>
31-
<path d='M310.22 803.025V0' stroke='#E7E4EF' strokeWidth='2' />
32-
<path
33-
d='M160 530.184C256.142 655.353 308.338 749.141 348.382 960'
34-
stroke='#E7E4EF'
35-
strokeWidth='2'
36-
/>
37-
<path d='M160 157.764V960' stroke='#E7E4EF' strokeWidth='2' />
38-
<path d='M-50 157.764L160 157.764' stroke='#E7E4EF' strokeWidth='2' />
39-
<circle cx='160' cy='157.764' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
40-
<circle cx='310.22' cy='803.025' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
41-
<circle cx='160' cy='530.184' r='8.07846' fill='white' stroke='#E7E4EF' strokeWidth='2' />
42-
</svg>
26+
{/* Top-right card outline */}
27+
<div
28+
aria-hidden='true'
29+
className='pointer-events-none absolute top-[-4vw] right-[-14vw] z-[5] aspect-[471/470] w-[42vw]'
30+
>
31+
<svg
32+
viewBox='0 0 471 470'
33+
fill='none'
34+
xmlns='http://www.w3.org/2000/svg'
35+
preserveAspectRatio='xMidYMid meet'
36+
className='h-full w-full'
37+
>
38+
<path
39+
d='M471 94.274L471 124.274L365.88 124.274C361.462 124.274 357.88 127.856 357.88 132.274L357.88 225.495C357.88 229.913 354.298 233.495 349.88 233.495L219.5 233.495C215.082 233.495 211.5 237.077 211.5 241.495L211.5 461.5C211.5 465.918 207.918 469.5 203.5 469.5L8.5 469.5C4.082 469.5 0.5 465.918 0.5 461.5L0.5 157.274C0.5 152.856 4.082 149.274 8.5 149.274L184 149.274C188.418 149.274 192 145.692 192 141.274L192 102.274C192 97.856 195.582 94.274 200 94.274L471 94.274Z'
40+
fill='#1C1C1C'
41+
stroke='#323232'
42+
strokeOpacity='0.4'
43+
strokeWidth='1'
44+
/>
45+
</svg>
46+
</div>
47+
48+
{/* Bottom-left card outline (mirrored) */}
49+
<div
50+
aria-hidden='true'
51+
className='pointer-events-none absolute bottom-[-6vw] left-[-12vw] z-[5] aspect-[471/470] w-[36vw] rotate-180'
52+
>
53+
<svg
54+
viewBox='0 0 471 470'
55+
fill='none'
56+
xmlns='http://www.w3.org/2000/svg'
57+
preserveAspectRatio='xMidYMid meet'
58+
className='h-full w-full'
59+
>
60+
<path
61+
d='M471 94.274L471 124.274L365.88 124.274C361.462 124.274 357.88 127.856 357.88 132.274L357.88 225.495C357.88 229.913 354.298 233.495 349.88 233.495L219.5 233.495C215.082 233.495 211.5 237.077 211.5 241.495L211.5 461.5C211.5 465.918 207.918 469.5 203.5 469.5L8.5 469.5C4.082 469.5 0.5 465.918 0.5 461.5L0.5 157.274C0.5 152.856 4.082 149.274 8.5 149.274L184 149.274C188.418 149.274 192 145.692 192 141.274L192 102.274C192 97.856 195.582 94.274 200 94.274L471 94.274Z'
62+
fill='#1C1C1C'
63+
stroke='#323232'
64+
strokeOpacity='0.4'
65+
strokeWidth='1'
66+
/>
67+
</svg>
68+
</div>
69+
70+
{/* Bottom-right card outline (mirrored) */}
71+
<div
72+
aria-hidden='true'
73+
className='pointer-events-none absolute right-[-12vw] bottom-[-5vw] z-[5] aspect-[344/328] w-[34vw] rotate-180'
74+
>
75+
<svg
76+
viewBox='0 0 344 328'
77+
fill='none'
78+
xmlns='http://www.w3.org/2000/svg'
79+
preserveAspectRatio='xMidYMid meet'
80+
className='h-full w-full'
81+
>
82+
<path
83+
d='M322.641 326.586L335.508 326.586C339.926 326.586 343.508 323.004 343.508 318.586V153.613C343.508 149.195 339.926 145.613 335.508 145.613H228.282C223.864 145.613 220.282 142.031 220.282 137.613V-50H190.282V137.613C190.282 142.031 186.7 145.613 182.282 145.613H-157V318.586C-157 323.004 -153.418 326.586 -149 326.586H322.641Z'
84+
fill='#1C1C1C'
85+
stroke='#323232'
86+
strokeOpacity='0.4'
87+
strokeWidth='1'
88+
/>
89+
</svg>
90+
</div>
91+
</>
4392
)
4493
}

apps/sim/app/(auth)/components/auth-background.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ type AuthBackgroundProps = {
88

99
export default function AuthBackground({ className, children }: AuthBackgroundProps) {
1010
return (
11-
<div className={cn('relative min-h-screen w-full overflow-hidden', className)}>
12-
<div className='-z-50 pointer-events-none fixed inset-0 bg-white' />
11+
<div className={cn('fixed inset-0 overflow-hidden', className)}>
12+
<div className='-z-50 pointer-events-none absolute inset-0 bg-[#1C1C1C]' />
1313
<AuthBackgroundSVG />
14-
<div className='relative z-20'>{children}</div>
14+
<div className='relative z-20 h-full overflow-auto'>{children}</div>
1515
</div>
1616
)
1717
}

apps/sim/app/(auth)/components/branded-button.tsx

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,20 @@
22

33
import { forwardRef, useState } from 'react'
44
import { ArrowRight, ChevronRight, Loader2 } from 'lucide-react'
5-
import { Button, type ButtonProps as EmcnButtonProps } from '@/components/emcn'
65
import { cn } from '@/lib/core/utils/cn'
7-
import { useBrandedButtonClass } from '@/hooks/use-branded-button-class'
6+
import { useBrandConfig } from '@/ee/whitelabeling'
87

9-
export interface BrandedButtonProps extends Omit<EmcnButtonProps, 'variant' | 'size'> {
10-
/** Shows loading spinner and disables button */
8+
export interface BrandedButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
119
loading?: boolean
12-
/** Text to show when loading (appends "..." automatically) */
1310
loadingText?: string
14-
/** Show arrow animation on hover (default: true) */
1511
showArrow?: boolean
16-
/** Make button full width (default: true) */
1712
fullWidth?: boolean
1813
}
1914

2015
/**
2116
* Branded button for auth and status pages.
22-
* Automatically detects whitelabel customization and applies appropriate styling.
23-
*
24-
* @example
25-
* ```tsx
26-
* // Primary branded button with arrow
27-
* <BrandedButton onClick={handleSubmit}>Sign In</BrandedButton>
28-
*
29-
* // Loading state
30-
* <BrandedButton loading loadingText="Signing in">Sign In</BrandedButton>
31-
*
32-
* // Without arrow animation
33-
* <BrandedButton showArrow={false}>Continue</BrandedButton>
34-
* ```
17+
* Default: white button matching the landing page "Get started" style.
18+
* Whitelabel: uses the brand's primary color as background with white text.
3519
*/
3620
export const BrandedButton = forwardRef<HTMLButtonElement, BrandedButtonProps>(
3721
(
@@ -49,7 +33,8 @@ export const BrandedButton = forwardRef<HTMLButtonElement, BrandedButtonProps>(
4933
},
5034
ref
5135
) => {
52-
const buttonClass = useBrandedButtonClass()
36+
const brand = useBrandConfig()
37+
const isWhitelabeled = brand.name !== 'Sim'
5338
const [isHovered, setIsHovered] = useState(false)
5439

5540
const handleMouseEnter = (e: React.MouseEvent<HTMLButtonElement>) => {
@@ -63,14 +48,31 @@ export const BrandedButton = forwardRef<HTMLButtonElement, BrandedButtonProps>(
6348
}
6449

6550
return (
66-
<Button
51+
<button
6752
ref={ref}
68-
variant='branded'
69-
size='branded'
7053
disabled={disabled || loading}
7154
onMouseEnter={handleMouseEnter}
7255
onMouseLeave={handleMouseLeave}
73-
className={cn(buttonClass, 'group', fullWidth && 'w-full', className)}
56+
className={cn(
57+
'group inline-flex h-[30px] items-center justify-center gap-[7px] rounded-[5px] border px-[9px] text-[13.5px] transition-colors disabled:cursor-not-allowed disabled:opacity-50',
58+
!isWhitelabeled &&
59+
'border-[#FFFFFF] bg-[#FFFFFF] text-black hover:border-[#E0E0E0] hover:bg-[#E0E0E0]',
60+
fullWidth && 'w-full',
61+
className
62+
)}
63+
style={
64+
isWhitelabeled
65+
? {
66+
backgroundColor: isHovered
67+
? (brand.theme?.primaryHoverColor ?? brand.theme?.primaryColor)
68+
: brand.theme?.primaryColor,
69+
borderColor: isHovered
70+
? (brand.theme?.primaryHoverColor ?? brand.theme?.primaryColor)
71+
: brand.theme?.primaryColor,
72+
color: '#FFFFFF',
73+
}
74+
: undefined
75+
}
7476
{...props}
7577
>
7678
{loading ? (
@@ -92,7 +94,7 @@ export const BrandedButton = forwardRef<HTMLButtonElement, BrandedButtonProps>(
9294
) : (
9395
children
9496
)}
95-
</Button>
97+
</button>
9698
)
9799
}
98100
)

apps/sim/app/(auth)/components/social-login-buttons.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
'use client'
22

33
import { type ReactNode, useEffect, useState } from 'react'
4+
import { Button } from '@/components/emcn'
45
import { GithubIcon, GoogleIcon } from '@/components/icons'
5-
import { Button } from '@/components/ui/button'
66
import { client } from '@/lib/auth/auth-client'
7-
import { inter } from '@/app/_styles/fonts/inter/inter'
87

98
interface SocialLoginButtonsProps {
109
githubAvailable: boolean
@@ -82,7 +81,7 @@ export function SocialLoginButtons({
8281
const githubButton = (
8382
<Button
8483
variant='outline'
85-
className='w-full rounded-[10px] shadow-sm hover:bg-gray-50'
84+
className='w-full rounded-[10px]'
8685
disabled={!githubAvailable || isGithubLoading}
8786
onClick={signInWithGithub}
8887
>
@@ -94,7 +93,7 @@ export function SocialLoginButtons({
9493
const googleButton = (
9594
<Button
9695
variant='outline'
97-
className='w-full rounded-[10px] shadow-sm hover:bg-gray-50'
96+
className='w-full rounded-[10px]'
9897
disabled={!googleAvailable || isGoogleLoading}
9998
onClick={signInWithGoogle}
10099
>
@@ -110,7 +109,7 @@ export function SocialLoginButtons({
110109
}
111110

112111
return (
113-
<div className={`${inter.className} grid gap-3 font-light`}>
112+
<div className='grid gap-3 font-light'>
114113
{googleAvailable && googleButton}
115114
{githubAvailable && githubButton}
116115
{children}

apps/sim/app/(auth)/components/sso-login-button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { useRouter } from 'next/navigation'
4-
import { Button } from '@/components/ui/button'
4+
import { Button } from '@/components/emcn'
55
import { getEnv, isTruthy } from '@/lib/core/config/env'
66
import { cn } from '@/lib/core/utils/cn'
77

@@ -38,7 +38,7 @@ export function SSOLoginButton({
3838
'flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200'
3939
)
4040

41-
const outlineBtnClasses = cn('w-full rounded-[10px] shadow-sm hover:bg-gray-50')
41+
const outlineBtnClasses = cn('w-full rounded-[10px]')
4242

4343
return (
4444
<Button

0 commit comments

Comments
 (0)