Écran de connexion : bouton afficher / masquer le mot de passe #134

Closed
opened 2026-09-09 13:20:28 +02:00 by kyuno · 0 comments
Owner

Contexte

Origine : ticket #3, puce 7 — « Sur l'onglet de connexion, pouvoir afficher/masquer le mot de passe ».

LoginPage a un <input id="password" type="password"> nu, sans bascule de visibilité (LoginPage.tsx:80-88). SignupPage a le même champ (SignupPage.tsx:100-108). Les deux pages partagent features/auth/auth-form.scss.

Comportement souhaité

Un bouton « œil » dans le champ mot de passe qui bascule type entre "password" et "text", sur l'écran de connexion (et, tant qu'on y est, l'inscription — même champ, même bénéfice).

Conception proposée

Un petit composant réutilisable apps/web/src/components/ui/PasswordInput.tsx (le dossier components/ui/ accueille déjà Checkbox/Radio/Tooltip/Dialog/BottomSheet) :

  • <input> dont le type vient d'un useState local ("password" / "text"), + <button type="button"> icône œil / œil-barré positionné en absolu dans le champ.
  • Icône dans le langage lucide-react du reste de l'app (Eye/EyeOff), ou 2 SVG inline stroke 24×24 (même approche que les icônes locales de TechStepCorrectionPopover).
  • aria-label traduit (« Afficher le mot de passe » / « Masquer le mot de passe »), aria-pressed. type="button" pour ne pas soumettre le formulaire.
  • Props passe-plat : id, value, onChange, autoComplete (current-password pour login, new-password pour signup).

Puis remplacer le <input type="password"> de LoginPage (et SignupPage) par <PasswordInput ...>.

SCSS : dans auth-form.scss, un wrapper position: relative autour du champ + le bouton en position: absolute; right: …. Prévoir le padding-right de l'input pour ne pas passer sous l'icône.

Découpage proposé

Une PR. Très petit.

Tests (obligatoires, cf. specs/dev-conventions.md)

  • Cypress mode composant cypress/component/PasswordInput.cy.tsx (composant autonome de components/ui/*) : au montage type="password" ; clic sur l'œil ⇒ type="text" et texte lisible ; reclic ⇒ masqué ; aria-label/aria-pressed corrects ; le clic ne soumet pas un <form> parent.
  • Cypress mode layout login (layout.cy.ts ou spec auth) : l'œil est présent et fonctionne sur /login.

Documentation à mettre à jour

  • Aucune (composant UI mineur). Éventuellement une ligne dans specs/frontend-architecture.md si la liste des composants components/ui/* y est tenue.

Points restant à trancher en revue

  • Périmètre : login seul (strict à la puce) ou login + signup (même champ, cohérent) ? Recommandé : les deux.
  • Icône : lucide-react (Eye/EyeOff) — déjà dépendance directe de apps/web (utilisé par la nav) — ou SVG inline.
  • Réinitialiser à « masqué » à chaque montage (oui) ; pas de persistance de la préférence.

🤖 Filed by Claude Code

## Contexte Origine : ticket #3, puce 7 — *« Sur l'onglet de connexion, pouvoir afficher/masquer le mot de passe »*. `LoginPage` a un `<input id="password" type="password">` nu, sans bascule de visibilité ([LoginPage.tsx:80-88](apps/web/src/pages/auth/LoginPage.tsx#L80-L88)). `SignupPage` a le même champ ([SignupPage.tsx:100-108](apps/web/src/pages/auth/SignupPage.tsx#L100-L108)). Les deux pages partagent `features/auth/auth-form.scss`. ## Comportement souhaité Un bouton « œil » dans le champ mot de passe qui bascule `type` entre `"password"` et `"text"`, sur l'écran de connexion (et, tant qu'on y est, l'inscription — même champ, même bénéfice). ## Conception proposée Un petit composant réutilisable `apps/web/src/components/ui/PasswordInput.tsx` (le dossier `components/ui/` accueille déjà `Checkbox`/`Radio`/`Tooltip`/`Dialog`/`BottomSheet`) : - `<input>` dont le `type` vient d'un `useState` local (`"password"` / `"text"`), + `<button type="button">` icône œil / œil-barré positionné en absolu dans le champ. - Icône dans le langage `lucide-react` du reste de l'app (`Eye`/`EyeOff`), ou 2 SVG inline stroke 24×24 (même approche que les icônes locales de `TechStepCorrectionPopover`). - `aria-label` traduit (« Afficher le mot de passe » / « Masquer le mot de passe »), `aria-pressed`. `type="button"` pour ne pas soumettre le formulaire. - Props passe-plat : `id`, `value`, `onChange`, `autoComplete` (`current-password` pour login, `new-password` pour signup). Puis remplacer le `<input type="password">` de `LoginPage` (et `SignupPage`) par `<PasswordInput ...>`. SCSS : dans `auth-form.scss`, un wrapper `position: relative` autour du champ + le bouton en `position: absolute; right: …`. Prévoir le `padding-right` de l'input pour ne pas passer sous l'icône. ## Découpage proposé Une PR. Très petit. ## Tests (obligatoires, cf. `specs/dev-conventions.md`) - **Cypress mode composant** `cypress/component/PasswordInput.cy.tsx` (composant autonome de `components/ui/*`) : au montage `type="password"` ; clic sur l'œil ⇒ `type="text"` et texte lisible ; reclic ⇒ masqué ; `aria-label`/`aria-pressed` corrects ; le clic ne soumet pas un `<form>` parent. - **Cypress mode layout** `login` (`layout.cy.ts` ou spec auth) : l'œil est présent et fonctionne sur `/login`. ## Documentation à mettre à jour - Aucune (composant UI mineur). Éventuellement une ligne dans `specs/frontend-architecture.md` si la liste des composants `components/ui/*` y est tenue. ## Points restant à trancher en revue - Périmètre : login seul (strict à la puce) ou login + signup (même champ, cohérent) ? Recommandé : les deux. - Icône : `lucide-react` (`Eye`/`EyeOff`) — déjà dépendance directe de `apps/web` (utilisé par la nav) — ou SVG inline. - Réinitialiser à « masqué » à chaque montage (oui) ; pas de persistance de la préférence. --- 🤖 Filed by [Claude Code](https://claude.com/claude-code)
kyuno added the
enhancement
planned
labels 2026-09-09 13:20:28 +02:00
kyuno added the
Low
label 2026-09-09 13:23:45 +02:00
kyuno closed this issue 2026-09-09 20:44:36 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/batchCooking#134
No description provided.