A lightweight npm package for sending emails via Gmail and beautiful OTP input components for React.
- Email Service: Simple Gmail-based email sending with minimal configuration
- OTP Input: Beautiful, accessible OTP input components with copy-paste support
- Themeable: Dark and light themes built-in
- Flexible: Multiple sizes (sm/md/lg) and customizable styles via classNames API
- Composable: Build custom layouts with InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator
- Easy to Use: Minimal API surface - just a few props to get started
- Type-Safe: Built with TypeScript
- Zero Config: Just add your Gmail credentials - no SMTP configuration needed
IrisMail works with all major package managers. No additional configuration is required.
npm install irismail
pnpm add irismail
yarn add irismail
bun add irismail| Import | Description |
|---|---|
irismail/server |
Email service (IrisMail class and types) |
irismail/react |
OTP components (OTP, InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator) |
irismail |
All exports (server + react + utils) |
Send emails with just your Gmail credentials:
import { IrisMail } from 'irismail/server';
const mail = new IrisMail({
auth: {
user: process.env.GMAIL_USER!,
pass: process.env.GMAIL_APP_PASSWORD!,
},
});
await mail.sendMail({
from: process.env.GMAIL_USER!,
to: 'user@example.com',
subject: 'Hello!',
html: '<h1>Welcome</h1><p>Thanks for signing up!</p>',
});Note: You'll need to generate a Gmail App Password for authentication.
'use client';
import { useState } from 'react';
import { OTP } from 'irismail/react';
export function VerifyForm() {
const [code, setCode] = useState('');
return (
<OTP
value={code}
onChange={setCode}
onComplete={(value) => verify(value)}
/>
);
}<OTP
value={code}
onChange={setCode}
error={isInvalid}
/><OTP length={4} value={code} onChange={setCode} />Use the theme prop to switch between dark and light color schemes:
// Dark theme (default)
<OTP theme="dark" value={code} onChange={setCode} />
// Light theme - for light backgrounds
<OTP theme="light" value={code} onChange={setCode} />Use the slotSize prop to change the slot dimensions:
<OTP slotSize="sm" value={code} onChange={setCode} />
<OTP slotSize="md" value={code} onChange={setCode} /> // default
<OTP slotSize="lg" value={code} onChange={setCode} />Add visual separators and control grouping:
// With separator (auto groups: 3-3 for 6 digits)
<OTP separator value={code} onChange={setCode} />
// Custom group size (2-2-2 for 6 digits)
<OTP separator groupSize={2} value={code} onChange={setCode} />
// Stripe-style (3-3 for 6 digits)
<OTP length={6} separator groupSize={3} value={code} onChange={setCode} />Use the classNames prop to customize individual parts:
<OTP
value={code}
onChange={setCode}
separator
groupSize={3}
classNames={{
slot: "rounded-none first:rounded-l-md last:rounded-r-md",
slotActive: "ring-2 ring-indigo-500 ring-offset-1 ring-offset-zinc-900",
separator: "mx-4",
separatorLine: "bg-indigo-500 w-4 h-0.5",
caret: "bg-indigo-400",
}}
/>For custom layouts, use the composition components:
import {
InputOTP,
InputOTPGroup,
InputOTPSlot,
InputOTPSeparator,
} from 'irismail/react';
<InputOTP maxLength={6} value={code} onChange={setCode}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>InputOTP and composition components support the same styling props: theme, slotSize, error, and classNames.
| Prop | Type | Default | Description |
|---|---|---|---|
length |
number | 6 | Number of OTP digits |
value |
string | — | Controlled input value |
onChange |
(value: string) => void | — | Called when value changes |
onComplete |
(value: string) => void | — | Called when all digits entered |
theme |
"dark" | "light" | "dark" | Color theme |
slotSize |
"sm" | "md" | "lg" | "md" | Size of the input slots |
separator |
boolean | false | Show separator between groups |
groupSize |
number | length / 2 | Number of slots per group when separator is enabled |
disabled |
boolean | false | Disable the input |
error |
boolean | false | Show error styling |
autoFocus |
boolean | false | Auto focus first slot |
name |
string | — | Name attribute for forms |
className |
string | — | Container className |
classNames |
OTPClassNames | — | Styles API for fine-grained customization |
pattern |
string | "^[0-9]*$" | Regex pattern to match input against |
The classNames prop accepts an object with these keys for custom styling:
| Key | Description |
|---|---|
root |
Root container element |
group |
Group wrapper containing slots |
slot |
Individual digit slot (base state) |
slotFilled |
Slot when it contains a digit |
slotActive |
Slot when focused/active |
slotError |
Slot in error state |
separator |
Separator container |
separatorLine |
The separator dash/line element |
caret |
Blinking caret cursor |
Works with both the OTP component and the composition components (InputOTP, etc.). OTP components work best with Tailwind CSS; use these class names to override or extend the default styles.
For full documentation and interactive examples, run the docs site:
npm run siteContributions are welcome.
-
Clone and install
git clone https://github.com/nitin-1926/irismail.git cd irismail npm install -
Build the package
npm run build
-
Develop with watch mode
npm run dev
-
Run the documentation site
npm run site
Then open http://localhost:3000.
-
Submit changes: Open a pull request with a clear description of the change. Ensure the build passes (
npm run build) and the package works with the docs site.
ISC