Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 2x 75x 75x 2x | // src/components/PasswordInput.tsx
import React, { useState } from 'react';
import { EyeIcon } from './icons/EyeIcon';
import { EyeSlashIcon } from './icons/EyeSlashIcon';
import { PasswordStrengthIndicator } from './PasswordStrengthIndicator';
/**
* Props for the PasswordInput component.
* It extends standard HTML input attributes and adds a custom prop to show a strength indicator.
*/
interface PasswordInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
showStrength?: boolean;
}
/**
* A reusable password input component with a show/hide toggle
* and an optional password strength indicator.
*/
export const PasswordInput: React.FC<PasswordInputProps> = ({
showStrength = false,
className,
...props
}) => {
const [showPassword, setShowPassword] = useState(false);
return (
<div>
<div className="relative">
<input
{...props}
type={showPassword ? 'text' : 'password'}
// Combine passed classNames with default styling
className={`block w-full px-3 py-2 pr-10 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-brand-primary focus:border-brand-primary sm:text-sm ${className || ''}`}
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute inset-y-0 right-0 flex items-center pr-3 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
aria-label={showPassword ? 'Hide password' : 'Show password'}
>
{showPassword ? <EyeSlashIcon className="h-5 w-5" /> : <EyeIcon className="h-5 w-5" />}
</button>
</div>
{showStrength && typeof props.value === 'string' && props.value.length > 0 && (
<div className="pt-2">
<PasswordStrengthIndicator password={props.value} />
</div>
)}
</div>
);
};
|