Type an email and press Enter to see the text dissolve into particles, then enter the OTP.
Inspired by @raunofreiberg.
Features
- Canvas-based particle dissipation effect
- Email validation with error states
- Smooth transition to OTP input
- Auto-focus on OTP field
- Shake animation for errors
- Customizable placeholders and callbacks
Usage
Full Email → OTP Flow
import DissipateInput from "./dissipate-input";
<DissipateInput
emailPlaceholder="sup@husnainfareed.dev"
otpPlaceholder="123456"
otpHelperText="check your email for a one-time password"
onEmailSubmit={(email) => {
// Send OTP to email
sendOTP(email);
}}
onOtpSubmit={(otp) => {
// Verify OTP
verifyOTP(otp);
}}
/>Email Only (No OTP)
<DissipateInput
showOtpStep={false}
onEmailSubmit={(email) => {
// Handle email submission
subscribeToNewsletter(email);
}}
/>Standalone Dissipation Effect
import { DissipateTextEffect } from "./dissipate-input";
<DissipateTextEffect
value="Hello World"
width={800}
height={120}
fontSize={24}
color="#FFFFFF"
sweepSpeed={8}
onDone={() => console.log("Animation complete")}
/>Props
DissipateInput
| Prop | Type | Default | Description |
|---|---|---|---|
emailPlaceholder | string | "sup@husnainfareed.dev" | Email input placeholder |
otpPlaceholder | string | "123456" | OTP input placeholder |
otpHelperText | string | "check your email..." | Helper text shown on OTP step |
showOtpStep | boolean | true | Show OTP input after email |
onEmailSubmit | (email: string) => void | - | Email submission callback |
onOtpSubmit | (otp: string) => void | - | OTP submission callback |
className | string | "" | Additional CSS classes |
DissipateTextEffect
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | Text to dissipate |
width | number | required | Canvas width (use 2x for retina) |
height | number | required | Canvas height (use 2x for retina) |
fontSize | number | 24 | Font size in pixels |
fontFamily | string | "PP Neue Montreal"... | Font family |
color | string | "#FFFFFF" | Text color |
sweepSpeed | number | 8 | Dissipation speed (px/frame) |
onReady | () => void | - | Called when particles are ready |
onDone | () => void | - | Called when animation completes |