-
Notifications
You must be signed in to change notification settings - Fork 62
Fixed issue #342 -- Add hide/unhide button for passwords in change password #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
e459724
544df63
f628812
7ec27ac
98f8864
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,11 +20,16 @@ import { CHANGE_PASSWORD_FORM_SCHEMA } from "@/constants/schema"; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getAccessToken } from '@/utils/getAccesstoken'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { enqueueSnackbar } from 'notistack'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useState, useEffect } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ChangePasswordFormType } from './ChangePasswordForm.types'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { ChangePasswordFormType } from './ChangePasswordForm.types'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { CHANGE_PASSWORD_FORM_FIELDS } from './ChangePasswordForm.config'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { FaEye, FaEyeSlash } from 'react-icons/fa'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ChangePasswordForm = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [accessToken, setAccessToken] = useState<string | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [showPassword, setShowPassword] = useState({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newPassword: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| confirmPassword: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fetchAccessToken = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -74,6 +79,10 @@ const ChangePasswordForm = () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const togglePasswordVisibility = (field: 'newPassword' | 'confirmPassword') => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setShowPassword((prev) => ({ ...prev, [field]: !prev[field] })); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Card className="mx-auto space-y-6 bg-transparent border-none shadow-none w-full"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <CardHeader className="px-0"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -90,7 +99,7 @@ const ChangePasswordForm = () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {CHANGE_PASSWORD_FORM_FIELDS.map((field) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div key={field.name} className="grid w-1/2 items-center gap-1.5"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div key={field.name} className="grid w-1/2 items-center gap-1.5 relative"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <FormField | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| control={control} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name={field.name} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -101,11 +110,30 @@ const ChangePasswordForm = () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </FormLabel> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <FormControl> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type={field.type} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder={field.placeholder} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {...formField} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field.name === 'newPassword' && showPassword.newPassword | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'text' : field.name === 'confirmPassword' && showPassword.confirmPassword | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'text' : | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field.type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder={field.placeholder} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {...formField} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </FormControl> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className='absolute right-1 top-1/2 -translate-y-1/4 bg-transparent text-foreground hover:bg-transparent mt-2 w-max' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={(e) => {e.preventDefault(); togglePasswordVisibility(field.name)}}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {field.name === 'newPassword' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? showPassword.newPassword | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? <FaEyeSlash size={18} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : <FaEye size={18} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : showPassword.confirmPassword | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? <FaEyeSlash size={18} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : <FaEye size={18} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+125
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add accessible name/state to the visibility toggle button. The icon-only button currently has no accessible name or pressed state, so screen-reader users will encounter an unlabeled control and cannot tell whether the password is visible. Please surface an accessible label that reflects the action (show/hide) and expose the toggle state via Apply this diff to address the issue: - <Button
- className='absolute right-1 top-1/2 -translate-y-1/4 bg-transparent text-foreground hover:bg-transparent mt-2 w-max'
- onClick={(e) => {e.preventDefault(); togglePasswordVisibility(field.name)}}>
+ <Button
+ type="button"
+ aria-label={
+ field.name === 'newPassword'
+ ? (showPassword.newPassword ? 'Hide new password' : 'Show new password')
+ : (showPassword.confirmPassword ? 'Hide confirm password' : 'Show confirm password')
+ }
+ aria-pressed={
+ field.name === 'newPassword'
+ ? showPassword.newPassword
+ : showPassword.confirmPassword
+ }
+ className='absolute right-1 top-1/2 -translate-y-1/4 bg-transparent text-foreground hover:bg-transparent mt-2 w-max'
+ onClick={() => togglePasswordVisibility(field.name)}>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {errors[field.name] && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <FormMessage>{errors[field.name]?.message}</FormMessage> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to preventDefault here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ig, since it is nested inside a form there is chance of it to be considered to be a submit action when clicked on it. Can be replaced with type="button"