feat: redesign admin login page to be ultra premium and fix tailwind keyframes

This commit is contained in:
2026-09-22 17:14:15 +05:30
parent 97d3569137
commit cb14f0d320
4 changed files with 111 additions and 60 deletions
+84 -51
View File
@@ -6,69 +6,102 @@ const LoginPage = () => {
const [credentials, setCredentials] = useState({ email: '', password: '' });
const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
setError('');
setIsLoading(true);
if (credentials.email === 'admin@limelite.com' && credentials.password === 'admin@2026') {
navigate('/admin/dashboard');
} else {
setError('Incorrect admin credentials');
}
// Simulate a slight network delay for a premium feel
setTimeout(() => {
if (credentials.email === 'admin@limelite.com' && credentials.password === 'admin@2026') {
navigate('/admin/dashboard');
} else {
setError('Incorrect admin credentials');
setIsLoading(false);
}
}, 800);
};
return (
<div className="min-h-screen bg-[#18181b] flex items-center justify-center p-4 font-sans">
<div className="bg-white w-full max-w-md p-10 shadow-2xl rounded-none">
<div className="flex flex-col items-center mb-10">
<div className="bg-limelite-red p-4 mb-6">
<img src={process.env.PUBLIC_URL + '/assets/images/logo.jpg'} alt="Limelite" className="h-8 brightness-0 invert" />
</div>
</div>
<div className="min-h-screen bg-gradient-to-br from-[#0a0a0a] via-[#1a1a24] to-[#2a0810] flex items-center justify-center p-4 font-sans relative overflow-hidden">
{/* Background Ambient Glows */}
<div className="absolute top-0 left-0 w-[500px] h-[500px] bg-limelite-red/20 rounded-full blur-[120px] -translate-x-1/2 -translate-y-1/2"></div>
<div className="absolute bottom-0 right-0 w-[500px] h-[500px] bg-limelite-maroon/20 rounded-full blur-[120px] translate-x-1/2 translate-y-1/2"></div>
{error && <p className="text-limelite-red text-sm font-bold text-center mb-6 animate-shake">{error}</p>}
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label className="block text-sm font-bold text-black uppercase tracking-wider mb-2">Email Address</label>
<input
type="email"
required
className="w-full border-b-2 border-gray-200 py-3 focus:outline-none focus:border-limelite-red transition-colors text-black"
placeholder="olivia@limelite.com"
value={credentials.email}
onChange={(e) => setCredentials({ ...credentials, email: e.target.value })}
/>
</div>
<div className="relative">
<label className="block text-sm font-bold text-black uppercase tracking-wider mb-2">Password</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
required
className="w-full border-b-2 border-gray-200 py-3 pr-10 focus:outline-none focus:border-limelite-red transition-colors text-black"
placeholder="••••••••"
value={credentials.password}
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
/>
<button
type="button"
className="absolute right-0 top-1/2 -translate-y-1/2 text-gray-400 hover:text-black transition-colors"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <FiEye size={20} /> : <FiEyeOff size={20} />}
</button>
<div className="w-full max-w-md relative z-10 animate-[fadeIn_0.5s_ease-out]">
<div className="backdrop-blur-xl bg-white/5 border border-white/10 p-10 shadow-2xl rounded-2xl">
<div className="flex flex-col items-center mb-10">
<div className="bg-gradient-to-tr from-limelite-maroon to-limelite-red p-1 rounded-2xl mb-6 shadow-lg shadow-limelite-red/30">
<div className="bg-black/40 backdrop-blur-md p-4 rounded-xl">
<img src={process.env.PUBLIC_URL + '/assets/images/logo.jpg'} alt="Limelite" className="h-8 brightness-0 invert opacity-90" />
</div>
</div>
<h2 className="text-3xl font-serif italic text-white tracking-wide">Admin Portal</h2>
<p className="text-gray-400 text-sm mt-2 font-light">Secure access to Limelite dashboard</p>
</div>
<button
type="submit"
className="w-full bg-limelite-red text-white py-4 font-bold uppercase tracking-widest hover:bg-limelite-maroon transition-colors mt-4"
>
Login
</button>
</form>
{error && (
<div className="bg-red-500/10 border border-red-500/20 rounded-lg p-3 mb-6 animate-shake">
<p className="text-red-400 text-sm font-semibold text-center">{error}</p>
</div>
)}
<form onSubmit={handleSubmit} className="space-y-6">
<div className="group">
<label className="block text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 group-focus-within:text-white transition-colors">Email Address</label>
<input
type="email"
required
className="w-full bg-white/5 border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-limelite-red focus:bg-white/10 transition-all"
placeholder="admin@limelite.com"
value={credentials.email}
onChange={(e) => setCredentials({ ...credentials, email: e.target.value })}
/>
</div>
<div className="relative group">
<label className="block text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 group-focus-within:text-white transition-colors">Password</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
required
className="w-full bg-white/5 border border-white/10 rounded-lg py-3 pl-4 pr-12 text-white placeholder-gray-500 focus:outline-none focus:border-limelite-red focus:bg-white/10 transition-all"
placeholder="••••••••"
value={credentials.password}
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
/>
<button
type="button"
className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-white transition-colors"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <FiEye size={18} /> : <FiEyeOff size={18} />}
</button>
</div>
</div>
<button
type="submit"
disabled={isLoading}
className="w-full relative overflow-hidden bg-gradient-to-r from-limelite-maroon to-limelite-red text-white py-4 font-bold uppercase tracking-widest rounded-lg hover:shadow-[0_0_20px_rgba(200,20,50,0.4)] transition-all active:scale-[0.98] disabled:opacity-70 disabled:cursor-wait mt-4 group"
>
{/* Hover shine effect */}
<div className="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent group-hover:animate-[shimmer_1.5s_infinite]"></div>
<span className="relative z-10 flex items-center justify-center gap-2">
{isLoading ? (
<>
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Authenticating...
</>
) : 'Login to Admin'}
</span>
</button>
</form>
</div>
</div>
</div>
);
+19
View File
@@ -17,6 +17,25 @@ module.exports = {
sans: ['"Albert Sans"', 'sans-serif'],
serif: ['"Playfair Display"', 'serif'],
},
keyframes: {
shimmer: {
'100%': { transform: 'translateX(100%)' },
},
fadeIn: {
'0%': { opacity: 0 },
'100%': { opacity: 1 },
},
shake: {
'0%, 100%': { transform: 'translateX(0)' },
'10%, 30%, 50%, 70%, 90%': { transform: 'translateX(-5px)' },
'20%, 40%, 60%, 80%': { transform: 'translateX(5px)' },
}
},
animation: {
shimmer: 'shimmer 1.5s infinite',
fadeIn: 'fadeIn 0.5s ease-out',
shake: 'shake 0.5s cubic-bezier(.36,.07,.19,.97) both',
}
},
},
plugins: [],