From 41e2ced7edb668ee602ecd418fbe5e9ddec653ce Mon Sep 17 00:00:00 2001 From: waleed Date: Wed, 21 Jan 2026 17:16:42 -0800 Subject: [PATCH] improvement(ui): use BrandedButton and BrandedLink components - Refactor auth forms to use BrandedButton component - Add BrandedLink component for changelog page - Reduce code duplication in login, signup, reset-password forms - Update star count default value --- apps/sim/app/(auth)/login/login-form.tsx | 46 +++++----------- .../reset-password/reset-password-form.tsx | 52 +++++-------------- apps/sim/app/(auth)/signup/signup-form.tsx | 25 +++------ apps/sim/app/(landing)/careers/page.tsx | 19 ++++--- apps/sim/app/(landing)/components/nav/nav.tsx | 6 ++- .../app/changelog/components/branded-link.tsx | 27 ++++++++++ .../components/changelog-content.tsx | 10 ++-- apps/sim/app/chat/[identifier]/chat.tsx | 2 +- 8 files changed, 78 insertions(+), 109 deletions(-) create mode 100644 apps/sim/app/changelog/components/branded-link.tsx diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-form.tsx index c0ed0cd6d4..a259a036fc 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-form.tsx @@ -2,10 +2,9 @@ import { useEffect, useState } from 'react' import { createLogger } from '@sim/logger' -import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react' +import { Eye, EyeOff } from 'lucide-react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' -import { Button } from '@/components/ui/button' import { Dialog, DialogContent, @@ -22,6 +21,7 @@ import { getBaseUrl } from '@/lib/core/utils/urls' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { inter } from '@/app/_styles/fonts/inter/inter' import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import { BrandedButton } from '@/app/(auth)/components/branded-button' 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' @@ -107,7 +107,6 @@ export default function LoginPage({ const [passwordErrors, setPasswordErrors] = useState([]) const [showValidationError, setShowValidationError] = useState(false) const buttonClass = useBrandedButtonClass() - const [isButtonHovered, setIsButtonHovered] = useState(false) const [callbackUrl, setCallbackUrl] = useState('/workspace') const [isInviteFlow, setIsInviteFlow] = useState(false) @@ -115,7 +114,6 @@ export default function LoginPage({ const [forgotPasswordOpen, setForgotPasswordOpen] = useState(false) const [forgotPasswordEmail, setForgotPasswordEmail] = useState('') const [isSubmittingReset, setIsSubmittingReset] = useState(false) - const [isResetButtonHovered, setIsResetButtonHovered] = useState(false) const [resetStatus, setResetStatus] = useState<{ type: 'success' | 'error' | null message: string @@ -491,24 +489,14 @@ export default function LoginPage({ - + Sign in + )} @@ -619,25 +607,15 @@ export default function LoginPage({

{resetStatus.message}

)} - + Send Reset Link + diff --git a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx index d50fbf9868..4bc30dba68 100644 --- a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx +++ b/apps/sim/app/(auth)/reset-password/reset-password-form.tsx @@ -1,13 +1,12 @@ 'use client' import { useState } from 'react' -import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react' -import { Button } from '@/components/ui/button' +import { Eye, EyeOff } from 'lucide-react' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { cn } from '@/lib/core/utils/cn' import { inter } from '@/app/_styles/fonts/inter/inter' -import { useBrandedButtonClass } from '@/hooks/use-branded-button-class' +import { BrandedButton } from '@/app/(auth)/components/branded-button' interface RequestResetFormProps { email: string @@ -28,9 +27,6 @@ export function RequestResetForm({ statusMessage, className, }: RequestResetFormProps) { - const buttonClass = useBrandedButtonClass() - const [isButtonHovered, setIsButtonHovered] = useState(false) - const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() onSubmit(email) @@ -68,24 +64,14 @@ export function RequestResetForm({ )} - + Send Reset Link + ) } @@ -112,8 +98,6 @@ export function SetNewPasswordForm({ const [validationMessage, setValidationMessage] = useState('') const [showPassword, setShowPassword] = useState(false) const [showConfirmPassword, setShowConfirmPassword] = useState(false) - const buttonClass = useBrandedButtonClass() - const [isButtonHovered, setIsButtonHovered] = useState(false) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() @@ -243,24 +227,14 @@ export function SetNewPasswordForm({ )} - + Reset Password + ) } diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-form.tsx index 840765de8c..bab806f23a 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-form.tsx @@ -2,10 +2,9 @@ import { Suspense, useEffect, useState } from 'react' import { createLogger } from '@sim/logger' -import { ArrowRight, ChevronRight, Eye, EyeOff } from 'lucide-react' +import { Eye, EyeOff } from 'lucide-react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' -import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { client, useSession } from '@/lib/auth/auth-client' @@ -14,6 +13,7 @@ import { cn } from '@/lib/core/utils/cn' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { inter } from '@/app/_styles/fonts/inter/inter' import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import { BrandedButton } from '@/app/(auth)/components/branded-button' 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' @@ -97,7 +97,6 @@ function SignupFormContent({ const [redirectUrl, setRedirectUrl] = useState('') const [isInviteFlow, setIsInviteFlow] = useState(false) const buttonClass = useBrandedButtonClass() - const [isButtonHovered, setIsButtonHovered] = useState(false) const [name, setName] = useState('') const [nameErrors, setNameErrors] = useState([]) @@ -476,24 +475,14 @@ function SignupFormContent({ - + Create account + )} diff --git a/apps/sim/app/(landing)/careers/page.tsx b/apps/sim/app/(landing)/careers/page.tsx index d756661aa1..7bd88b4932 100644 --- a/apps/sim/app/(landing)/careers/page.tsx +++ b/apps/sim/app/(landing)/careers/page.tsx @@ -4,7 +4,6 @@ import { useRef, useState } from 'react' import { createLogger } from '@sim/logger' import { X } from 'lucide-react' import { Textarea } from '@/components/emcn' -import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { @@ -18,6 +17,7 @@ import { isHosted } from '@/lib/core/config/feature-flags' import { cn } from '@/lib/core/utils/cn' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import { BrandedButton } from '@/app/(auth)/components/branded-button' import Footer from '@/app/(landing)/components/footer/footer' import Nav from '@/app/(landing)/components/nav/nav' @@ -493,18 +493,17 @@ export default function CareersPage() { {/* Submit Button */}
- + {submitStatus === 'success' ? 'Submitted' : 'Submit Application'} +
diff --git a/apps/sim/app/(landing)/components/nav/nav.tsx b/apps/sim/app/(landing)/components/nav/nav.tsx index 0478a69a12..ff9e8787ec 100644 --- a/apps/sim/app/(landing)/components/nav/nav.tsx +++ b/apps/sim/app/(landing)/components/nav/nav.tsx @@ -11,6 +11,7 @@ import { useBrandConfig } from '@/lib/branding/branding' import { isHosted } from '@/lib/core/config/feature-flags' import { soehne } from '@/app/_styles/fonts/soehne/soehne' import { getFormattedGitHubStars } from '@/app/(landing)/actions/github' +import { useBrandedButtonClass } from '@/hooks/use-branded-button-class' const logger = createLogger('nav') @@ -20,11 +21,12 @@ interface NavProps { } export default function Nav({ hideAuthButtons = false, variant = 'landing' }: NavProps = {}) { - const [githubStars, setGithubStars] = useState('25.1k') + const [githubStars, setGithubStars] = useState('25.8k') const [isHovered, setIsHovered] = useState(false) const [isLoginHovered, setIsLoginHovered] = useState(false) const router = useRouter() const brand = useBrandConfig() + const buttonClass = useBrandedButtonClass() useEffect(() => { if (variant !== 'landing') return @@ -183,7 +185,7 @@ export default function Nav({ hideAuthButtons = false, variant = 'landing' }: Na href='/signup' onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} - className='group inline-flex items-center justify-center gap-2 rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] py-[6px] pr-[10px] pl-[12px] text-[14px] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all sm:text-[16px]' + className={`${buttonClass} group inline-flex items-center justify-center gap-2 rounded-[10px] py-[6px] pr-[10px] pl-[12px] text-[15px] text-white transition-all`} aria-label='Get started with Sim - Sign up for free' prefetch={true} > diff --git a/apps/sim/app/changelog/components/branded-link.tsx b/apps/sim/app/changelog/components/branded-link.tsx new file mode 100644 index 0000000000..f126c320ac --- /dev/null +++ b/apps/sim/app/changelog/components/branded-link.tsx @@ -0,0 +1,27 @@ +'use client' + +import Link from 'next/link' +import { useBrandedButtonClass } from '@/hooks/use-branded-button-class' + +interface BrandedLinkProps { + href: string + children: React.ReactNode + className?: string + target?: string + rel?: string +} + +export function BrandedLink({ href, children, className = '', target, rel }: BrandedLinkProps) { + const buttonClass = useBrandedButtonClass() + + return ( + + {children} + + ) +} diff --git a/apps/sim/app/changelog/components/changelog-content.tsx b/apps/sim/app/changelog/components/changelog-content.tsx index 36c817e7f1..e0eefc3324 100644 --- a/apps/sim/app/changelog/components/changelog-content.tsx +++ b/apps/sim/app/changelog/components/changelog-content.tsx @@ -2,6 +2,7 @@ import { BookOpen, Github, Rss } from 'lucide-react' import Link from 'next/link' import { inter } from '@/app/_styles/fonts/inter/inter' import { soehne } from '@/app/_styles/fonts/soehne/soehne' +import { BrandedLink } from '@/app/changelog/components/branded-link' import ChangelogList from '@/app/changelog/components/timeline-list' export interface ChangelogEntry { @@ -66,25 +67,24 @@ export default async function ChangelogContent() {
- View on GitHub - + Documentation RSS Feed diff --git a/apps/sim/app/chat/[identifier]/chat.tsx b/apps/sim/app/chat/[identifier]/chat.tsx index 926f96a064..94082ffec2 100644 --- a/apps/sim/app/chat/[identifier]/chat.tsx +++ b/apps/sim/app/chat/[identifier]/chat.tsx @@ -117,7 +117,7 @@ export default function ChatClient({ identifier }: { identifier: string }) { const [error, setError] = useState(null) const messagesEndRef = useRef(null) const messagesContainerRef = useRef(null) - const [starCount, setStarCount] = useState('25.1k') + const [starCount, setStarCount] = useState('25.8k') const [conversationId, setConversationId] = useState('') const [showScrollButton, setShowScrollButton] = useState(false)