Ajout de la possibilité de voir le mot de passe

This commit is contained in:
2026-07-03 18:31:59 +02:00
parent 3c5aa635c4
commit 563063ba17
7 changed files with 69 additions and 15 deletions
+48
View File
@@ -0,0 +1,48 @@
import { useState } from 'react';
/**
* Champ mot de passe avec bouton "afficher/masquer".
* Utilisation : remplacer <input type="password" .../> par <PasswordInput .../>
* Toutes les props (className, value, onChange, required, autoComplete, style, etc.)
* sont transmises telles quelles à l'<input> sous-jacent.
*/
function EyeIcon({ open }) {
return open ? (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z" stroke="var(--text-muted)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<circle cx="12" cy="12" r="3" stroke="var(--text-muted)" strokeWidth="2"/>
</svg>
) : (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
<path d="M17.94 17.94A10.94 10.94 0 0112 19c-7 0-11-7-11-7a20.6 20.6 0 015.06-5.94M9.9 4.24A10.9 10.9 0 0112 4c7 0 11 7 11 7a20.6 20.6 0 01-2.66 3.78M14.12 14.12a3 3 0 11-4.24-4.24" stroke="var(--text-muted)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<line x1="1" y1="1" x2="23" y2="23" stroke="var(--text-muted)" strokeWidth="2" strokeLinecap="round"/>
</svg>
);
}
export default function PasswordInput({ style, wrapperStyle, ...props }) {
const [show, setShow] = useState(false);
return (
<div style={{ position: 'relative', ...wrapperStyle }}>
<input
{...props}
type={show ? 'text' : 'password'}
style={{ ...style, paddingRight: 40 }}
/>
<button
type="button"
tabIndex={-1}
onClick={() => setShow(v => !v)}
aria-label={show ? 'Masquer le mot de passe' : 'Afficher le mot de passe'}
style={{
position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)',
background: 'none', border: 'none', padding: 4, display: 'flex',
alignItems: 'center', justifyContent: 'center', cursor: 'pointer', lineHeight: 0,
}}
>
<EyeIcon open={show} />
</button>
</div>
);
}