133 lines
6.4 KiB
TypeScript
133 lines
6.4 KiB
TypeScript
import { useState } from 'react';
|
|
import { Eye, EyeOff } from 'lucide-react';
|
|
|
|
const inputClasses = [
|
|
'h-12 w-full rounded-lg',
|
|
'border border-white/30 bg-white/15',
|
|
'px-4 py-3 text-white placeholder:text-white/50',
|
|
'outline-none transition-all duration-200',
|
|
'focus:border-white/50 focus:ring-2 focus:ring-white/40',
|
|
'focus:ring-offset-2 focus:ring-offset-transparent',
|
|
'focus-visible:ring-2 focus-visible:ring-white/40',
|
|
'focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',
|
|
].join(' ');
|
|
|
|
function PasswordField(): JSX.Element {
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium text-white" htmlFor="password">
|
|
Password
|
|
</label>
|
|
<div className="relative">
|
|
<input
|
|
id="password"
|
|
aria-label="Password"
|
|
type={showPassword ? 'text' : 'password'}
|
|
placeholder="Enter your password"
|
|
className={`${inputClasses} pr-12`}
|
|
/>
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowPassword((prev) => !prev)}
|
|
className="absolute inset-y-0 right-3 flex items-center text-white/70"
|
|
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
|
>
|
|
{showPassword ? <EyeOff size={20} /> : <Eye size={20} />}
|
|
</button>
|
|
</div>
|
|
<div className="text-right">
|
|
<a
|
|
className="text-sm text-white transition-colors duration-200 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent focus-visible:underline"
|
|
href="#"
|
|
>
|
|
Forgot your password?
|
|
</a>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function SocialButtons(): JSX.Element {
|
|
return (
|
|
<div className="flex gap-3">
|
|
<button
|
|
type="button"
|
|
onClick={() => console.log('Google sign in clicked')}
|
|
className="flex h-12 flex-1 items-center justify-center gap-2 rounded-lg bg-white text-sm font-medium text-[#374151] transition-all duration-300 hover:scale-[1.02] hover:bg-[#F3F4F6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
>
|
|
<span aria-hidden="true" className="h-5 w-5 rounded-full bg-white">
|
|
<svg viewBox="0 0 48 48" className="h-5 w-5">
|
|
<path fill="#EA4335" d="M24 9.5c3.05 0 5.8 1.05 7.95 3.1l5.9-5.9C33.45 2.6 29.05.5 24 .5 14.95.5 7 6.8 4.05 15.05l6.95 5.4C12.8 14.7 17.9 9.5 24 9.5z" />
|
|
<path fill="#34A853" d="M46.5 24.5c0-1.55-.15-3.05-.45-4.5H24v9h12.7c-.55 2.95-2.2 5.45-4.7 7.15l7.3 5.65C43.55 38.65 46.5 32.15 46.5 24.5z" />
|
|
<path fill="#FBBC05" d="M10.95 28.85a14.52 14.52 0 0 1-.8-4.35c0-1.5.3-2.95.8-4.35l-6.95-5.4C1.35 17.9.5 21.1.5 24.5s.85 6.6 2.7 9.75l7.75-5.4z" />
|
|
<path fill="#4285F4" d="M24 47.5c5.05 0 9.35-1.65 12.45-4.5l-7.3-5.65c-2.05 1.35-4.7 2.15-7.15 2.15-6.1 0-11.2-5.2-12.1-11.95l-7.95 6.1C7 41.2 14.95 47.5 24 47.5z" />
|
|
<path fill="none" d="M0 0h48v48H0z" />
|
|
</svg>
|
|
</span>
|
|
Sign in with Google
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => console.log('Azure sign in clicked')}
|
|
className="flex h-12 flex-1 items-center justify-center gap-2 rounded-lg bg-white text-sm font-medium text-[#374151] transition-all duration-300 hover:scale-[1.02] hover:bg-[#F3F4F6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
>
|
|
<span aria-hidden="true" className="h-5 w-5 rounded-sm bg-[#0078D4]" />
|
|
Sign in with Azure
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function SignInCard(): JSX.Element {
|
|
return (
|
|
<div className="w-full max-w-[90%] sm:max-w-[480px] rounded-3xl bg-gradient-to-b from-[#17C1B7] to-[#0A2B5C] p-8 sm:p-12 lg:p-16 shadow-2xl">
|
|
<header className="text-center">
|
|
<h2 className="text-2xl sm:text-3xl font-semibold text-white">Sign In to Your Account</h2>
|
|
<p className="mt-2 text-sm text-white/80">Welcome back. Please enter your credentials.</p>
|
|
</header>
|
|
|
|
<form className="mt-8 space-y-5">
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium text-white" htmlFor="email">
|
|
Email
|
|
</label>
|
|
<input
|
|
id="email"
|
|
aria-label="Email"
|
|
type="email"
|
|
placeholder="Enter your email address"
|
|
className={inputClasses}
|
|
/>
|
|
</div>
|
|
|
|
<PasswordField />
|
|
|
|
<button
|
|
type="button"
|
|
onClick={() => console.log('Sign In clicked')}
|
|
className="h-[52px] w-full rounded-lg bg-[#00D9C8] text-base font-semibold text-[#1E293B] transition-all duration-300 hover:scale-[1.02] hover:bg-[#00C0B0] active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
>
|
|
Sign In
|
|
</button>
|
|
|
|
<SocialButtons />
|
|
|
|
<p className="text-center text-sm text-white/90">
|
|
Don't have an account?{' '}
|
|
<a
|
|
className="font-medium text-white transition-colors duration-200 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
href="#"
|
|
>
|
|
Register here
|
|
</a>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default SignInCard;
|
|
|