All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 12m10s
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
// 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>
|
|
);
|
|
};
|