OTP
The OTP component provides a One-Time Password input with a countdown timer, resend functionality, and customizable UI.
It supports integration with form flows that require SMS, email, or Absher verification.
import { OTP } from "tawuniya/components";
👉 View in Storybook
Props​
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Custom title displayed above the OTP input. |
description | string | — | Custom description displayed below the title. |
channel | string | — | Channel for OTP delivery (e.g., phone/email). Automatically masked. |
initialMinutes | number | 0 | Initial countdown minutes. |
initialSeconds | number | 59 | Initial countdown seconds. |
isAbsher | boolean | false | If true, shows the Absher style with Absher icon. |
centered | boolean | false | If true, centers content horizontally. |
disabled | boolean | false | Disables OTP input and actions. |
className | string | — | Additional Tailwind classes for the wrapper. |
verifyOTP | (otp: string) => void | — | Callback fired when clicking the Verify button. |
resendOTP | () => void | — | Callback fired when clicking the Resend button (after countdown ends). |
hideIcon | boolean | false | Hides the otp icon. |
disableAutoSubmitting | boolean | false | Disables auto submitting OTP when all slots are filled. |
viewType | "normal" | "modal" | normal | Controls whether the OTP is displayed in normal view or inside a modal. |
openModal | boolean | false | Controls the modal visibility. |
onOpenModal | Dispatch<SetStateAction<boolean>> | false | Controls the modal visibility. |
Usage​
Basic Example​
import { OTP } from "tawuniya/components";
export default function BasicExample() {
return (
<OTP
title="Verify your identity"
description="Enter the code sent to you"
/>
);
}
With Channel Masking​
<OTP
title="Enter OTP"
description="We have sent a code to"
channel="+966500000000"
verifyOTP={(otp) => console.log("Submitted OTP:", otp)}
resendOTP={() => console.log("Resend triggered")}
/>
With Custom Countdown​
<OTP initialMinutes={1} initialSeconds={30} />
With Absher Branding​
<OTP isAbsher centered />
With Hide Icon​
<OTP hideIcon />
With Disable Auto Submitting​
<OTP
disableAutoSubmitting
verifyOTP={(otp) => console.log("Submitted OTP:", otp)}
/>
With Modal​
const [openModal, setOpenModal] = useState(false);
<OTP
title="Enter OTP"
description="We have sent a code to"
channel="+966500000000"
verifyOTP={(otp) => {
console.log("Submitted OTP:", otp);
setOpenModal(false);
}}
resendOTP={() => console.log("Resend triggered")}
viewType="modal"
openModal={openModal}
onOpenModal={setOpenModal}
/>;
Notes​
- OTP input is 4 digits by default.
- The Resend button becomes active only after the countdown reaches 0.
- channel is automatically masked for security (e.g., +966******000).
- If isAbsher is true, the Absher branding will be displayed instead of Tawuniya.
- The Verify button is disabled until 4 digits are entered.