diff --git a/client/modules/User/components/AccountForm.jsx b/client/modules/User/components/AccountForm.jsx index 5be633b594..67ba40e2ba 100644 --- a/client/modules/User/components/AccountForm.jsx +++ b/client/modules/User/components/AccountForm.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useState } from 'react'; import { Form, Field } from 'react-final-form'; import { useSelector, useDispatch } from 'react-redux'; import { useTranslation } from 'react-i18next'; @@ -25,6 +26,17 @@ function asyncValidate(fieldToValidate, value) { } function AccountForm() { + const [showCurrentPassword, setShowCurrentPassword] = useState(false); + const [showNewPassword, setShowNewPassword] = useState(false); + + const toggleCurrentPasswordVisibility = () => { + setShowCurrentPassword(!showCurrentPassword); + }; + + const toggleConfirmPasswordVisibility = () => { + setShowNewPassword(!showNewPassword); + }; + const { t } = useTranslation(); const user = useSelector((state) => state.user); const dispatch = useDispatch(); @@ -134,14 +146,32 @@ function AccountForm() { - +
+ + { + if (e.key === 'Enter') { + toggleCurrentPasswordVisibility(); + } + }} + > + {showCurrentPassword + ? t('AccountForm.HidePassword') + : t('AccountForm.ShowPassword')} + +
+ {field.meta.touched && field.meta.error && ( {field.meta.error} )} @@ -154,14 +184,32 @@ function AccountForm() { - +
+ + { + if (e.key === 'Enter') { + toggleConfirmPasswordVisibility(); + } + }} + > + {showNewPassword + ? t('AccountForm.HidePassword') + : t('AccountForm.ShowPassword')} + +
+ {field.meta.touched && field.meta.error && ( {field.meta.error} )} diff --git a/client/modules/User/components/LoginForm.jsx b/client/modules/User/components/LoginForm.jsx index d990299322..c92420ab21 100644 --- a/client/modules/User/components/LoginForm.jsx +++ b/client/modules/User/components/LoginForm.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -7,6 +8,8 @@ import { validateLogin } from '../../../utils/reduxFormUtils'; import { validateAndLoginUser } from '../actions'; function LoginForm() { + const [showPassword, setShowPassword] = useState(false); + const { t } = useTranslation(); const dispatch = useDispatch(); @@ -14,6 +17,10 @@ function LoginForm() { return dispatch(validateAndLoginUser(formProps)); } + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; + return (
{(field) => ( -

- - - {field.meta.touched && field.meta.error && ( - {field.meta.error} - )} -

+ <> +

+ +

+ + { + if (e.key === 'Enter') { + togglePasswordVisibility(); + } + }} + > + {showPassword + ? t('LoginForm.HidePassword') + : t('LoginForm.ShowPassword')} + +
+ {field.meta.touched && field.meta.error && ( + {field.meta.error} + )} +

+ )}
{submitError && !modifiedSinceLastSubmit && ( diff --git a/client/modules/User/components/SignupForm.jsx b/client/modules/User/components/SignupForm.jsx index c497981c1e..368fee03a1 100644 --- a/client/modules/User/components/SignupForm.jsx +++ b/client/modules/User/components/SignupForm.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Form, Field } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -33,6 +34,17 @@ function validateEmail(email) { } function SignupForm() { + const [showPassword, setShowPassword] = useState(false); + const [ConfirmShowPassword, setConfirmShowPassword] = useState(false); + + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; + + const toggleConfirmPasswordVisibility = () => { + setConfirmShowPassword(!ConfirmShowPassword); + }; + const { t } = useTranslation(); const dispatch = useDispatch(); @@ -98,14 +110,32 @@ function SignupForm() { - +
+ + { + if (e.key === 'Enter') { + togglePasswordVisibility(); + } + }} + > + {showPassword + ? t('SignupForm.HidePassword') + : t('SignupForm.ShowPassword')} + +
+ {field.meta.touched && field.meta.error && ( {field.meta.error} )} @@ -118,14 +148,31 @@ function SignupForm() { - +
+ + { + if (e.key === 'Enter') { + toggleConfirmPasswordVisibility(); + } + }} + > + {ConfirmShowPassword + ? t('SignupForm.HidePassword') + : t('SignupForm.ShowPassword')} + +
{field.meta.touched && field.meta.error && ( {field.meta.error} )} diff --git a/client/styles/components/_forms.scss b/client/styles/components/_forms.scss index 6daa1fa67a..a0009b819f 100644 --- a/client/styles/components/_forms.scss +++ b/client/styles/components/_forms.scss @@ -117,3 +117,25 @@ // .form--inline [type="submit"][disabled] { // cursor: not-allowed; // } + +.password-input-container { + position: relative; +} + +.form__input { + padding-right: 35px; +} + +.show-hide-button { + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + border: none; + cursor: pointer; + outline: none; +} + +:focus-visible { + outline-color: lightgreen; +} \ No newline at end of file diff --git a/translations/locales/en-US/translations.json b/translations/locales/en-US/translations.json index 39f3a426ef..e709369d95 100644 --- a/translations/locales/en-US/translations.json +++ b/translations/locales/en-US/translations.json @@ -67,7 +67,9 @@ "UsernameOrEmailARIA": "Email or Username", "Password": "Password", "PasswordARIA": "Password", - "Submit": "Log In" + "Submit": "Log In", + "ShowPassword": "Show", + "HidePassword": "Hide" }, "LoginView": { "Title": "p5.js Web Editor | Login", @@ -311,7 +313,9 @@ "CurrentPasswordARIA": "Current Password", "NewPassword": "New Password", "NewPasswordARIA": "New Password", - "SubmitSaveAllSettings": "Save All Settings" + "SubmitSaveAllSettings": "Save All Settings", + "ShowPassword": "Show", + "HidePassword": "Hide" }, "AccountView": { "SocialLogin": "Social Login", @@ -357,7 +361,9 @@ "PasswordARIA": "password", "ConfirmPassword": "Confirm Password", "ConfirmPasswordARIA": "Confirm password", - "SubmitSignup": "Sign Up" + "SubmitSignup": "Sign Up", + "ShowPassword": "Show", + "HidePassword": "Hide" }, "SignupView": { "Title": "p5.js Web Editor | Signup",