Fluid Password Strength Gauge
A smooth, interpolating bar that physically stretches and continuously shifts color from red (weak) to yellow (fair) to green (strong) as the user types.
Use
User registration
Avoid
Standard non-sensitive data inputs
Safer Alternative
No safer default listed.
Risk Level
Low risk
Live Demo
What It Is
A smooth, interpolating bar that physically stretches and continuously shifts color from red (weak) to yellow (fair) to green (strong) as the user types.
✓When to Use
- User registration
- Password reset forms
- Security setting pages
✕When NOT to Use
- Standard non-sensitive data inputs
Configuration Tips
- 01Use Framer Motion to animate the `width` and `backgroundColor` of a single div simultaneously.
You've Seen It In
AI Implementation Prompts
Move from a fast scaffold to production details, then tune timing and edge states.
Create a password strength indicator line that animates its width and color from red (20%) to yellow (50%) to green (100%) based on input character count.
Reference Implementation
The same implementation approach used by the live preview, kept compact enough to inspect and adapt.
"use client";
import { motion } from 'framer-motion';
import { useState, useEffect } from 'react';
export function PasswordStrengthGaugeDemo({ isPlaying = false }: { isPlaying?: boolean }) {
const [password, setPassword] = useState("");
useEffect(() => {
if (!isPlaying) {
setPassword("");
return;
}
const typed = "Tr0ub4dor&3";
let index = 0;
const loop = setInterval(() => {
if (index <= typed.length) {
setPassword(typed.substring(0, index));
index++;
} else {
clearInterval(loop);
setTimeout(() => setPassword(""), 1000);
}
}, 200);
const restartLoop = setInterval(() => {
index = 0;
setPassword("");
}, 4000);
return () => {
clearInterval(loop);
clearInterval(restartLoop);
};
}, [isPlaying]);
"text-stone-400 italic">// Calculate strength based on length (simplified for demo)
const strength = Math.min(100, (password.length / 10) * 100);
"text-stone-400 italic">// Determine color
const getColor = (str: number) => {
if (str === 0) return "#e5e7eb"; "text-stone-400 italic">// stone-200
if (str < 40) return "#ef4444"; "text-stone-400 italic">// red-500
if (str < 80) return "#eab308"; "text-stone-400 italic">// yellow-500
return "#10b981"; "text-stone-400 italic">// emerald-500
};
const getLabel = (str: number) => {
if (str === 0) return "Enter password";
if (str < 40) return "Weak";
if (str < 80) return "Fair";
return "Strong";
};
return (
<div className="flex h-64 w-full items-center justify-center overflow-hidden rounded-2xl bg-white p-4 shadow-sm ring-1 ring-stone-200">
<div className="w-full max-w-xs flex flex-col gap-3">
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter password"
className="w-full rounded-lg border border-stone-200 bg-stone-50 px-4 py-3 outline-none focus:border-indigo-500 focus:bg-white transition-colors"
/>
{"text-stone-400 italic">/* The Gauge */}
<div className="flex flex-col gap-1.5 px-1">
<div className="h-1.5 w-full bg-stone-100 rounded-full overflow-hidden">
<motion.div
className="h-full rounded-full"
animate={{
width: `${strength}%`,
backgroundColor: getColor(strength)
}}
transition={{ type: "spring", stiffness: 200, damping: 20 }}
/>
</div>
<div className="flex justify-between items-center text-xs">
<span className="text-stone-400 font-medium">Security</span>
<motion.span
key={getLabel(strength)}
initial={{ opacity: 0, y: 5 }}
animate={{ opacity: 1, y: 0 }}
className="font-bold uppercase tracking-wider"
style={{ color: strength === 0 ? "#9ca3af" : getColor(strength) }}
>
{getLabel(strength)}
</motion.span>
</div>
</div>
</div>
</div>
);
}Related Effects
Progress Bar
A horizontal bar that fills from left to right, showing the percentage of a task that's complete. Gives users a sense of how much longer they need to wait.
Form Validation Error
Small red helper text that gracefully slides down from underneath an input field the moment the user tabs away with an invalid entry.