Skip to content
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

feat: add password visibility button to authentication pages #572

Merged
merged 14 commits into from
Nov 24, 2023
92 changes: 60 additions & 32 deletions components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import { forwardRef, InputHTMLAttributes } from "react";

interface Props extends InputHTMLAttributes<HTMLInputElement> {
export interface InputBaseProps
extends Pick<InputHTMLAttributes<HTMLDivElement>, "id" | "children"> {
text: string;
autocomplete?: string;
fgColor: string;
bgColor: string;
enabled?: boolean;
}

export default forwardRef<HTMLInputElement, Props>(function Input(
{
text,
id,
name,
type,
value,
autocomplete,
fgColor,
bgColor,
onChange,
enabled,
...rest
},
ref
) {
export interface InputDefaultProps
extends InputBaseProps,
InputHTMLAttributes<HTMLInputElement> {}

// A wrapper to the <input> to standardize styles for the container
export function InputBase({
text,
id,
fgColor,
bgColor,
enabled,
children,
}: InputBaseProps) {
let textColor = `text-${fgColor}`;
let backColor = `bg-${bgColor}`;

Expand All @@ -43,21 +40,52 @@ export default forwardRef<HTMLInputElement, Props>(function Input(
>
{text}
</label>
<div className="mt-2">
<input
id={id}
name={name}
type={type}
autoComplete={autocomplete}
value={value}
required
className={`text-iregular ${textColor} ${backColor} block w-full appearance-none rounded-full border border-gray-300 px-3 py-2 pl-6 placeholder-gray-400 shadow-sm focus:outline-none sm:text-sm`}
onChange={onChange}
disabled={enabled == false}
ref={ref}
{...rest}
/>
<div
className={`text-iregular mt-2 flex items-center ${textColor} ${backColor} appearance-none rounded-full border border-gray-300 px-3 py-2 pl-6 placeholder-gray-400 shadow-sm sm:text-sm`}
>
{children}
</div>
</div>
);
}

export default forwardRef<HTMLInputElement, InputDefaultProps>(function Input(
{
text,
id,
name,
type,
value,
autoComplete,
fgColor,
bgColor,
onChange,
enabled,
...rest
},
ref
) {
return (
<InputBase
text={text}
id={id}
fgColor={fgColor}
bgColor={bgColor}
enabled={enabled}
>
<input
id={id}
name={name}
type={type}
autoComplete={autoComplete}
value={value}
required
className="w-full bg-transparent outline-none"
onChange={onChange}
disabled={enabled == false}
ref={ref}
{...rest}
/>
</InputBase>
);
});
45 changes: 45 additions & 0 deletions components/PasswordInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { forwardRef, useState } from "react";

import { InputBase, InputDefaultProps } from "@components/Input";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";

export default forwardRef<HTMLInputElement, InputDefaultProps>(
function PasswordInput(
{ text, id, name, type, fgColor, bgColor, enabled, ...rest },
ref
) {
const [isPasswordVisible, setIsPasswordVisible] = useState(false);

const togglePasswordVisibility = () => {
setIsPasswordVisible(!isPasswordVisible);
};

return (
<InputBase
text={text}
id={id}
fgColor={fgColor}
bgColor={bgColor}
enabled={enabled}
>
<input
id={id}
name={name}
type={isPasswordVisible ? "text" : "password"}
required
className="w-full bg-transparent outline-none"
disabled={enabled == false}
ref={ref}
{...rest}
/>
<FontAwesomeIcon
className="mx-2 cursor-pointer"
onClick={togglePasswordVisibility}
icon={isPasswordVisible ? faEyeSlash : faEye}
/>
</InputBase>
);
}
);
5 changes: 2 additions & 3 deletions layout/Login/components/LoginForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Text from "@layout/moonstone/authentication/Text";

import Form from "@components/Form";
import Input from "@components/Input";
import PasswordInput from "@components/PasswordInput";

export default function LoginForm() {
const { errors, login, isLoading } = useAuth();
Expand Down Expand Up @@ -35,14 +36,12 @@ export default function LoginForm() {
autoComplete="email"
ref={emailRef}
/>
<Input
<PasswordInput
text="YOUR PASSWORD"
id="password"
name="password"
type="password"
fgColor="white"
bgColor="primary"
autoComplete="current-password"
ref={passwordRef}
/>
<Text
Expand Down
10 changes: 3 additions & 7 deletions layout/ResetPassword/components/ResetPasswordForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Button from "@components/Button";
import ImageButton from "@components/ImageButton";

import Form from "@components/Form";
import Input from "@components/Input";
import PasswordInput from "@components/PasswordInput";

export default function ResetPasswordForm() {
const router = useRouter();
Expand Down Expand Up @@ -51,22 +51,18 @@ export default function ResetPasswordForm() {
<>
{success === null && (
<Form onSubmit={onSubmit}>
<Input
<PasswordInput
text="PASSWORD"
id="password"
name="password"
type="password"
autoComplete="current-password"
fgColor="white"
bgColor="primary"
ref={passwordRef}
/>
<Input
<PasswordInput
text="CONFIRM PASSWORD"
id="confirm"
name="confirm"
type="password"
autoComplete="current-password"
fgColor="white"
bgColor="primary"
ref={passwordConfirmationRef}
Expand Down
13 changes: 5 additions & 8 deletions layout/SignUp/components/SignUpForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useAuth } from "@context/Auth";
import Button from "@components/Button";
import Form from "@components/Form";
import Input from "@components/Input";
import PasswordInput from "@components/PasswordInput";

import BarebonesQRScanner from "@components/QRScanner/BarebonesQRScanner";

Expand Down Expand Up @@ -92,22 +93,18 @@ export default function SignUpForm() {
bgColor="primary"
onChange={(e) => updateNickname(e.currentTarget.value)}
/>
<Input
<PasswordInput
text="PASSWORD"
id="password"
name="password"
type="password"
autoComplete="current-password"
fgColor="white"
bgColor="primary"
onChange={(e) => updatePassword(e.currentTarget.value)}
/>
<Input
<PasswordInput
text="CONFIRM PASSWORD"
id="password"
Darguima marked this conversation as resolved.
Show resolved Hide resolved
name="password"
type="password"
autoComplete="current-password"
id="confirm"
name="confirm"
fgColor="white"
bgColor="primary"
onChange={(e) => updatePasswordConfirmation(e.currentTarget.value)}
Expand Down
15 changes: 6 additions & 9 deletions pages/register/[uuid].js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Card from "@components/Card";
import Return from "@components/Return";
import Form from "@components/Form";
import Input from "@components/Input";
import PasswordInput from "@components/PasswordInput";

import Title from "@layout/moonstone/authentication/Title";
import Text from "@layout/moonstone/authentication/Text";
Expand Down Expand Up @@ -68,22 +69,18 @@ function Register() {
bgColor="primary"
onChange={(e) => updateNickname(e.currentTarget.value)}
/>
<Input
<PasswordInput
text="PASSWORD"
id="password"
id="confirm"
name="password"
type="password"
autoComplete="current-password"
fgColor="white"
bgColor="primary"
onChange={(e) => updatePassword(e.currentTarget.value)}
/>
<Input
<PasswordInput
text="CONFIRM PASSWORD"
id="password"
name="password"
type="password"
autoComplete="current-password"
id="confirm"
name="confirm"
fgColor="white"
bgColor="primary"
onChange={(e) => updatePasswordConfirmation(e.currentTarget.value)}
Expand Down
Loading