AuthCode 10.17.4
A one-time password (OTP) is an automatically generated numeric or alphanumeric string of characters that authenticates a user for a single transaction or login session.
Authcode component is designed for entering OTP codes;it is usually positioned through your UI in places like:
- Login
- OTP check
Default
"use client";
import { useCallback, useState } from "react";
import { AuthCode } from "@heathmont/moon-core-tw";
export const Default = () => {
const [result, setResult] = useState("");
const handleOnChange = useCallback((res: string) => {
setResult(res);
}, []);
return <AuthCode onChange={handleOnChange} />;
};
export default Default;
Using React Hook Form with Manual Submit
The AuthCode component can be utilized in conjunction with Controller component from React Hook Form library.
In this instance, the user is required to click the button to submit the code.
"use client";
import { AuthCode, Button, Form } from "@heathmont/moon-core-tw";
import { Controller, useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
authCode: z
.string()
.length(6, { message: "Must be exactly 6 characters long" }),
});
type ValidationSchema = z.infer<typeof schema>;
export const WithManualSubmit = () => {
const {
control,
handleSubmit,
formState: { isValid, isDirty },
} = useForm({
defaultValues: {
authCode: "",
},
resolver: zodResolver(schema),
});
const onSubmit: SubmitHandler<ValidationSchema> = (data: ValidationSchema) =>
alert(data.authCode);
return (
<Form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-2">
<Controller
name="authCode"
control={control}
render={({ field }) => <AuthCode {...field} />}
/>
<Button as="button" type="submit" disabled={!isDirty || !isValid}>
Send code
</Button>
</Form>
);
};
export default WithManualSubmit;
Using React Hook Form with Automatic Submit
In this scenario, there's no need for the user to manually trigger the submit;the submit occurs once the code have length 6 characters in this specific example.
"use client";
import { AuthCode, Form } from "@heathmont/moon-core-tw";
import { Controller, useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
authCode: z
.string()
.length(6, { message: "Must be exactly 6 characters long" }),
});
type ValidationSchema = z.infer<typeof schema>;
export const WithAutoSubmit = () => {
const { control, handleSubmit } = useForm({
defaultValues: {
authCode: "",
},
resolver: zodResolver(schema),
});
const onSubmit: SubmitHandler<ValidationSchema> = ({ authCode }) => {
if (authCode.length === 6) {
alert(`Code sent: "${authCode}"`);
}
};
return (
<Form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="authCode"
control={control}
render={({ field }) => (
<AuthCode
{...field}
onChange={(value: string) => {
field.onChange(value);
onSubmit({ authCode: value });
}}
/>
)}
/>
</Form>
);
};
export default WithAutoSubmit;
Allow only specific characters
The default setting allows you to input any characters in the field. However, you have the option to restrict it to only letters (alpha) or only numeric input (numeric) using the dedicated prop allowedCharacters
.
In this example the component is restrict to numeric only characters.
"use client";
import { useCallback, useState } from "react";
import { AuthCode } from "@heathmont/moon-core-tw";
export const AllowedCharacters = () => {
const [result, setResult] = useState("");
const handleOnChange = useCallback((res: string) => {
setResult(res);
}, []);
return <AuthCode allowedCharacters="numeric" onChange={handleOnChange} />;
};
export default AllowedCharacters;
Custom length
AuthCode component offers flexibility by adapting on the length of the input. Using the length
prop.
It allow you to meet with your OTP needs to specific length criteria.
In this example the length of the OTP is limited to 4.
"use client";
import { AuthCode, Form } from "@heathmont/moon-core-tw";
import { Controller, useForm } from "react-hook-form";
export const CustomLength = () => {
const { control, handleSubmit } = useForm({
defaultValues: {
authCode: "",
},
});
const codeLength = 4;
const onSubmit = ({ authCode }: { authCode: string }) => {
if (authCode.length === codeLength) alert(`Code sent: "${authCode}"`);
};
return (
<Form
onSubmit={handleSubmit(onSubmit)}
className="flex flex-col justify-between items-end gap-y-2"
>
<Controller
name="authCode"
control={control}
render={({ field }) => (
<AuthCode
{...field}
length={codeLength}
onChange={(value: string) => {
field.onChange(value);
onSubmit({ authCode: value });
}}
disabled={field.value.length === codeLength}
/>
)}
/>
</Form>
);
};
export default CustomLength;
Handling Errors
The isValid
prop provides you the option to show a visual error to the user the input a not valid OTP. It can be used also for show not valid OTP after the validation process.
This example uses the component <Hint error />
to show an additional message, that requires OTP to be at least 3 characters long
"use client";
import { useEffect } from "react";
import { AuthCode, Form, Hint } from "@heathmont/moon-core-tw";
import { Controller, useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { GenericInfo } from "@heathmont/moon-icons-tw";
const schema = z.object({
authCode: z.string().min(3, { message: "Must be 3 or more characters long" }),
});
type ValidationSchema = z.infer<typeof schema>;
export const ErrorState = () => {
const {
control,
handleSubmit,
formState: { isValid, errors },
trigger,
} = useForm({
defaultValues: {
authCode: "",
},
resolver: zodResolver(schema),
});
const onSubmit: SubmitHandler<ValidationSchema> = (data: ValidationSchema) =>
console.log("onSubmit: ", data);
// Trigger validation for this example
useEffect(() => {
trigger("authCode");
}, [trigger]);
return (
<Form
onSubmit={handleSubmit(onSubmit)}
className="flex items-center flex-col"
>
<Controller
name="authCode"
control={control}
render={({ field }) => (
<>
<AuthCode {...field} isValid={isValid} />
{!isValid && (
<Hint error>
<GenericInfo />
{errors.authCode?.message}
</Hint>
)}
</>
)}
/>
</Form>
);
};
export default ErrorState;
Display a hint message
The previous example uses the component <Hint />
to display an error, but this component can be utilized in conjunction with AuthCode to show additional hints to the user.
Hint message
"use client";
import { useState } from "react";
import { AuthCode, Hint } from "@heathmont/moon-core-tw";
export const HintMessage = () => {
const [result, setResult] = useState("");
const handleOnChange = (res: string) => {
setResult(res);
};
return (
<div className="flex items-center flex-col">
<AuthCode onChange={handleOnChange} />
<Hint>Hint message</Hint>
</div>
);
};
export default HintMessage;
Display a placeholder
You can utilize the prop placeholder
to display a OTP code as a placeholder in your input. The placeholder
can be of any length.
"use client";
import { useState } from "react";
import { AuthCode } from "@heathmont/moon-core-tw";
export const Placeholder = () => {
const [result, setResult] = useState("");
const handleOnChange = (res: string) => {
setResult(res);
};
return <AuthCode onChange={handleOnChange} placeholder="123456" />;
};
export default Placeholder;
Hide your input
You can make use of the prop isPassword
to hide the user input. This prop prevents the characters from being visible on the display.
"use client";
import { useState } from "react";
import { AuthCode } from "@heathmont/moon-core-tw";
export const Password = () => {
const [result, setResult] = useState("");
const handleOnChange = (res: string) => {
setResult(res);
};
return <AuthCode onChange={handleOnChange} isPassword />;
};
export default Password;
Different spacing between inputs
"use client";
import { useState } from "react";
import { AuthCode } from "@heathmont/moon-core-tw";
export const DifferentGaps = () => {
const [result1, setResult1] = useState("");
const handleOnChange1 = () => {
setResult1(result1);
};
const [result12, setResult2] = useState("");
const handleOnChange2 = () => {
setResult2(result12);
};
return (
<div className="flex flex-col items-center gap-4">
<AuthCode onChange={handleOnChange1} />
<AuthCode onChange={handleOnChange2} className="gap-4" />
</div>
);
};
export default DifferentGaps;
AuthCode
These are props specific to the AuthCode component:
Name | Type | Default |
---|---|---|
onChange* | (value: string) => {} | - |
length | number | 6 |
allowedCharacters | "alphanumeric" | "numeric" | "alpha" | alphanumeric |
autoFocus | boolean | false |
isPassword | boolean | false |
disabled | boolean | false |
placeholder | string | - |
isValid | boolean | true |
className | string | - |
ariaLabel | string | "Character `${i + 1}`" |
Properties indicated with * are required.