DEV Community

Saurabh Paryani
Saurabh Paryani

Posted on

Creating a simple Show/Hide Password feature in Nextjs Forms

This is a simple blog on how you can add a simple eye icon next to the password field of your login/sign up form.
The end result would look something like:

Show Password

What we want:

  1. An eye off icon next to the password field only after the password field has some non-empty value inside
  2. When clicked on eye off, it should reveal password and the icon should change to eye.

All you need for this is:

  1. 2 React Icons (RiEyeFill and RiEyeOffFill) (you can search for other icons on [https://react-icons.github.io/react-icons])
  2. Knowledge of the useState hook in React

So let me take you with what I'm working. I have a form component in Nextjs using the React-Hook-Form and other components by ShadcnUI.

Let's say we're working on the login form (you can follow the same steps for the signup as well)

In the login form, I have 2 form fields.

Form Fields

An email field and a password field.

Step 1: Import the React icons.
import { RiEyeFill, RiEyeOffFill } from "react-icons/ri";

Step 2: Go all the way down to your password field input.
For me, it looks like:

Password Form Field

Try rendering an icon here. In order to render it next to the password, wrap the Input in a div and add a button in the same row using flex.

                  <FormControl>
                    <div className="flex flex-row">
                      <Input
                        placeholder="******"
                        type="password"
                        {...field}
                        disabled={isPending}
                      />
                      <button className="ml-4 text-gray-700">
                        <RiEyeOffFill />
                      </button>
                    </div>
                  </FormControl>
Enter fullscreen mode Exit fullscreen mode

Step 2.1

But what I want is that the icon should be displayed only when there is something inside the password field.
For that, create a state at the top:

const [isPasswordTyping, setIsPasswordTyping] = useState(false);

Inside the Input tag, whenever there is a change in the password field, create an onChange event that sets this isPasswordTyping to true. Or rather, length > 0.

onChange={(e) => {
     field.onChange(e);
     setIsPasswordTyping(e.target.value.length > 0);
  }}
Enter fullscreen mode Exit fullscreen mode

This field is something that Shadcn's React-Hook-Form provides.

Finally render the button only if isPasswordTyping is true.
So now, you will only see the icon rendered if the password has a non empty field inside.

                  <FormControl>
                    <div className="flex flex-row">
                      <Input
                        placeholder="******"
                        type="password"
                        {...field}
                        onChange={(e) => {
                          field.onChange(e);
                          setIsPasswordTyping(e.target.value.length > 0);
                        }}
                        disabled={isPending}
                      />
                      {isPasswordTyping && (
                        <button className="ml-4 text-gray-700">
                          <RiEyeOffFill />
                        </button>
                      )}
                    </div>
                  </FormControl>
Enter fullscreen mode Exit fullscreen mode

Step 3: Toggle Visibility and change icon

We need to render the password as text if a variable "showPassword" is true, and the password as password (******) if "showPassword" is false.

For that create a state,
const [showPassword, setShowPassword] = useState(false);

and in the Input, add the line: type={showPassword ? "text" : "password"}

                      <Input
                        placeholder="******"
                        type={showPassword ? "text" : "password"}
                        {...field}
                        onChange={(e) => {
                          field.onChange(e);
                          setIsPasswordTyping(e.target.value.length > 0);
                        }}
                        disabled={isPending}
                      />
Enter fullscreen mode Exit fullscreen mode

We need to render the icon. if showPassword is true, then we need to render the EyeFill icon, else the EyeOffFill.

<button className="ml-4 text-gray-700">
    {showPassword ? <RiEyeFill /> : <RiEyeOffFill />}
</button>
Enter fullscreen mode Exit fullscreen mode

Finally, we need to add an onClick to this button and toggle the visibility.

const togglePasswordVisibility = () => {
    setShowPassword((prev) => !prev);
 };
Enter fullscreen mode Exit fullscreen mode
<button type="button" onClick={togglePasswordVisibility} className="ml-4 text-gray-700">
    {showPassword ? <RiEyeFill /> : <RiEyeOffFill />}
</button>
Enter fullscreen mode Exit fullscreen mode

And we're done. Here's a live demo:

Demo Gif

Thanks for reading. Let me know if you have any questions!
Happy coding.

Saurabh Paryani

Top comments (0)