learning_ai_common_plat/packages/auth-ui/src/PasswordStrengthBar.tsx
saravanakumardb1 43439e9c85 feat(auth-ui): complete Auth UI Kit (3.2) — 7 new components, 54 tests
New components:
- RegisterForm — name, email, password, confirm, terms, password strength
- ForgotPasswordForm — email input with success/error states, back link
- ResetPasswordForm — new password + confirm with strength indicator
- VerifyEmailForm — 6-digit code input with resend, numeric-only filter
- OnboardingShell — step indicator, progress bar, back/next/complete nav
- AuthPageLayout — full-page centered card with product branding
- PasswordStrengthBar — visual bar + label (weak/fair/good/strong)

Existing components preserved: LoginForm, MfaChallenge, SocialButtons
All styled via --bl-* CSS custom properties for product theming
54 tests (13 existing + 41 new) — all passing
2026-03-19 20:25:57 -07:00

68 lines
2.0 KiB
TypeScript

import { useMemo } from 'react';
import type { PasswordStrength } from './types.js';
interface PasswordStrengthBarProps {
password: string;
className?: string;
}
const STRENGTH_CONFIG: Record<PasswordStrength, { color: string; label: string }> = {
weak: { color: 'var(--bl-error, #dc3545)', label: 'Weak' },
fair: { color: 'var(--bl-warning, #f59e0b)', label: 'Fair' },
good: { color: 'var(--bl-info, #3b82f6)', label: 'Good' },
strong: { color: 'var(--bl-success, #22c55e)', label: 'Strong' },
};
export function getPasswordStrength(password: string): PasswordStrength {
let score = 0;
if (password.length >= 8) score++;
if (password.length >= 12) score++;
if (/[A-Z]/.test(password)) score++;
if (/[a-z]/.test(password)) score++;
if (/\d/.test(password)) score++;
if (/[^A-Za-z0-9]/.test(password)) score++;
if (score <= 2) return 'weak';
if (score <= 3) return 'fair';
if (score <= 4) return 'good';
return 'strong';
}
export function PasswordStrengthBar({ password, className }: PasswordStrengthBarProps) {
const strength = useMemo(() => getPasswordStrength(password), [password]);
const config = STRENGTH_CONFIG[strength];
const widthPercent = { weak: 25, fair: 50, good: 75, strong: 100 }[strength];
if (!password) return null;
return (
<div className={className} data-testid="bl-password-strength">
<div
style={{
height: '4px',
borderRadius: '2px',
background: 'var(--bl-border, #e5e7eb)',
overflow: 'hidden',
}}
>
<div
style={{
height: '100%',
width: `${widthPercent}%`,
background: config.color,
transition: 'width 0.2s, background 0.2s',
borderRadius: '2px',
}}
data-testid="bl-password-strength-fill"
/>
</div>
<div
style={{ fontSize: '12px', color: config.color, marginTop: '4px' }}
data-testid="bl-password-strength-label"
>
{config.label}
</div>
</div>
);
}