Created
April 28, 2026 15:27
-
-
Save joshmosh/16db579571c7bae6d5378318682a0e77 to your computer and use it in GitHub Desktop.
ACUL Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useEffect } from 'react'; | |
| import { useForm } from 'react-hook-form'; | |
| import { yupResolver } from '@hookform/resolvers/yup'; | |
| import type { InferType } from 'yup'; | |
| import { | |
| login, | |
| useErrors, | |
| useScreen, | |
| useUntrustedData, | |
| } from '@auth0/auth0-acul-react/login'; | |
| import { FORGOT_PASSWORD_URL } from '@/constants/externalUrls'; | |
| import useAuthParams from '@/lib/hooks/useAuthParams'; | |
| import useCustomization from '@/lib/hooks/useCustomization'; | |
| import useToast from '@/lib/hooks/useToast'; | |
| import { loginSchema } from '@/lib/schemas/loginSchema'; | |
| import Input from '@/ui/Input'; | |
| import Button from '@/ui/Button'; | |
| import Typography from '@/ui/Typography'; | |
| import Link from '@/ui/Link'; | |
| import Captcha from '@/components/Captcha'; | |
| import LegalLinks from '@/components/LegalLinks'; | |
| type LoginFormData = InferType<typeof loginSchema>; | |
| const LoginForm = () => { | |
| const [captchaToken, setCaptchaToken] = useState(''); | |
| const [hasSubmitted, setHasSubmitted] = useState(false); | |
| const { hasError, errors: loginErrors } = useErrors(); | |
| const { toast } = useToast(); | |
| const { loginCta } = useCustomization(); | |
| const { submittedFormData } = useUntrustedData(); | |
| const { qaPassword } = useAuthParams(); | |
| const screen = useScreen(); | |
| useEffect(() => { | |
| if (hasError) { | |
| setHasSubmitted(false); | |
| toast({ | |
| id: 'login-error', | |
| title: 'Oops! Something went wrong.', | |
| description: loginErrors.map((error) => error.message).join(', '), | |
| variant: 'error', | |
| }); | |
| } | |
| }, [hasError, loginErrors, toast]); | |
| const { | |
| register, | |
| handleSubmit, | |
| formState: { errors: formErrors, isValid }, | |
| } = useForm<LoginFormData>({ | |
| resolver: yupResolver(loginSchema), | |
| mode: 'onTouched', | |
| defaultValues: { | |
| email: (submittedFormData?.username as string) || '', | |
| password: qaPassword || '', | |
| }, | |
| }); | |
| const onSubmit = async (data: LoginFormData) => { | |
| setHasSubmitted(true); | |
| await login({ | |
| username: data.email, | |
| password: data.password, | |
| captcha: screen.isCaptchaAvailable ? captchaToken.trim() : '', | |
| }); | |
| }; | |
| return ( | |
| <> | |
| <form onSubmit={handleSubmit(onSubmit)} data-testid="login-form"> | |
| <Input | |
| className="mb-2" | |
| data-testid="email-input" | |
| label="Email" | |
| type="email" | |
| autoComplete="email" | |
| error={!!formErrors.email} | |
| errorMessage={formErrors.email?.message} | |
| {...register('email')} | |
| /> | |
| <Input | |
| className="mb-6" | |
| data-testid="password-input" | |
| label="Password" | |
| type="password" | |
| error={!!formErrors.password} | |
| errorMessage={formErrors.password?.message} | |
| {...register('password')} | |
| /> | |
| <Typography variant="bodySm" align="center" className="mb-4"> | |
| <Link data-testid="forgot-password-link" href={FORGOT_PASSWORD_URL}> | |
| Forgot your password? | |
| </Link> | |
| </Typography> | |
| {screen.isCaptchaAvailable && ( | |
| <Captcha | |
| className="mb-2 flex justify-center" | |
| screen={screen} | |
| onToken={setCaptchaToken} | |
| /> | |
| )} | |
| <div className="mb-4"> | |
| <LegalLinks ctaCopy={loginCta} isSignUp={false} /> | |
| </div> | |
| <Button | |
| data-testid="login-button" | |
| block | |
| type="submit" | |
| disabled={!isValid || hasSubmitted} | |
| > | |
| {loginCta} | |
| </Button> | |
| </form> | |
| {screen.signupLink && ( | |
| <div className="mt-6"> | |
| <Typography light align="center" className="mb-2"> | |
| Don't have an account? | |
| </Typography> | |
| <Button | |
| data-testid="sign-up-link" | |
| block | |
| variant="secondary" | |
| href={screen.signupLink} | |
| > | |
| Sign Up | |
| </Button> | |
| </div> | |
| )} | |
| </> | |
| ); | |
| }; | |
| export default LoginForm; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment