{"id":11087,"library":"input-otp","title":"input-otp React Component","description":"input-otp is a comprehensive and highly flexible React component designed for creating accessible one-time password (OTP) input fields. Currently stable at version 1.4.2, it is actively maintained with consistent updates to support modern React environments and best practices. A key differentiator is its unstyled nature, empowering developers with full control over the visual presentation through a render prop API, making it adaptable to any design system or CSS framework. It stands out by offering robust accessibility features, automatic OTP code retrieval from SMS via `autocomplete='one-time-code'`, and seamless copy-paste-cut functionality across iOS and Android devices, addressing common pitfalls of custom OTP implementations.","status":"active","version":"1.4.2","language":"javascript","source_language":"en","source_url":"https://github.com/guilhermerodz/input-otp","tags":["javascript","react","otp","input","accessible","typescript"],"install":[{"cmd":"npm install input-otp","lang":"bash","label":"npm"},{"cmd":"yarn add input-otp","lang":"bash","label":"yarn"},{"cmd":"pnpm add input-otp","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core React library for component functionality.","package":"react","optional":false},{"reason":"Required for rendering React components to the DOM.","package":"react-dom","optional":false}],"imports":[{"note":"OTPInput is a named export. When used in frameworks like Next.js App Router, the file containing this component or its parent must include `'use client'` at the top.","wrong":"const OTPInput = require('input-otp')","symbol":"OTPInput","correct":"import { OTPInput } from 'input-otp'"},{"note":"This is a TypeScript type used for defining the props passed to custom slot components in the render prop. Use `import type` for clarity and stricter type checking.","wrong":"import { SlotProps } from 'input-otp'","symbol":"SlotProps","correct":"import type { SlotProps } from 'input-otp'"},{"note":"This is a TypeScript type defining all available props for the main OTPInput component. Use `import type` for clarity and stricter type checking.","wrong":"import { OTPInputProps } from 'input-otp'","symbol":"OTPInputProps","correct":"import type { OTPInputProps } from 'input-otp'"}],"quickstart":{"code":"'use client'\nimport { OTPInput, SlotProps } from 'input-otp'\nimport { clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\nimport type { ClassValue } from 'clsx'\n\n// Small utility to merge class names (commonly used with Tailwind CSS).\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n\n// Custom Slot component to render individual OTP digits.\nfunction Slot(props: SlotProps) {\n  return (\n    <div\n      className={cn(\n        'relative w-10 h-14 text-[2rem]',\n        'flex items-center justify-center',\n        'transition-all duration-300',\n        'border-border border-y border-r first:border-l first:rounded-l-md last:rounded-r-md',\n        'group-hover:border-accent-foreground/20 group-focus-within:border-accent-foreground/20',\n        'outline outline-0 outline-accent-foreground/20',\n        { 'outline-4 outline-accent-foreground': props.isActive }\n      )}\n    >\n      <div className=\"group-has-[input[data-input-otp-placeholder-shown]]:opacity-20\">\n        {props.char ?? props.placeholderChar}\n      </div>\n      {props.hasFakeCaret && <FakeCaret />}\n    </div>\n  )\n}\n\n// Emulates a blinking caret for visual feedback.\nfunction FakeCaret() {\n  return (\n    <div className=\"absolute pointer-events-none inset-0 flex items-center justify-center animate-caret-blink\">\n      <div className=\"w-px h-8 bg-white\" />\n    </div>\n  )\n}\n\n// A visual separator, inspired by Stripe's MFA input.\nfunction FakeDash() {\n  return (\n    <div className=\"flex w-10 justify-center items-center\">\n      <div className=\"w-3 h-1 rounded-full bg-border\" />\n    </div>\n  )\n}\n\n// Example form component using OTPInput.\nexport default function MyOTPForm() {\n  return (\n    <form className=\"flex gap-2\"> {/* Added a wrapper form for context */}\n      <OTPInput\n        maxLength={6}\n        containerClassName=\"group flex items-center has-[:disabled]:opacity-30\"\n        render={({ slots }) => (\n          <>\n            <div className=\"flex\">\n              {slots.slice(0, 3).map((slot, idx) => (\n                <Slot key={idx} {...slot} />\n              ))}\n            </div>\n\n            <FakeDash />\n\n            <div className=\"flex\">\n              {slots.slice(3).map((slot, idx) => (\n                <Slot key={idx} {...slot} />\n              ))}\n            </div>\n          </>\n        )}\n      />\n    </form>\n  )\n}","lang":"typescript","description":"Demonstrates how to render a custom styled 6-digit OTP input using the `render` prop, including a blinking caret and a dash separator, leveraging common Tailwind CSS utilities for visual presentation."},"warnings":[{"fix":"Add `'use client'` at the very top of the file where `OTPInput` or a component rendering it is defined.","message":"When using `input-otp` within React frameworks that support Server Components (like Next.js App Router), the component or its parent must be marked with the `'use client'` directive to ensure it runs in the browser environment.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Apply custom CSS or utilize utility-first CSS frameworks (e.g., Tailwind CSS) through the `containerClassName` prop and by implementing custom components within the `render` prop to achieve the desired look.","message":"The `input-otp` component is intentionally unstyled, requiring developers to provide all visual styling themselves. It does not ship with any default CSS.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If password manager interference is observed, you might need to adjust the `pushPasswordManagerStrategy` prop (e.g., to `\"none\"`) and potentially implement custom workarounds or block specific password managers manually.","message":"While `input-otp` includes logic to automatically shift password manager badges, some password managers might still interfere with the UI.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Add `'use client'` as the very first line of code in the file where the `OTPInput` component is imported or rendered.","cause":"Attempting to use `OTPInput` in a Server Component context (e.g., Next.js App Router) without marking it as a Client Component.","error":"Error: You're importing a component that needs 'useState'. It only works in a Client Component - add the 'use client' directive at the top of the file to turn it into one."},{"fix":"Ensure the `render` prop explicitly returns JSX elements (`React.ReactNode`) and correctly destructures the `{ slots }` argument, using `SlotProps` for type safety if defining custom slot components. Verify your TypeScript configuration is properly set up for JSX.","cause":"Incorrect type inference or usage of the `render` prop, typically when TypeScript is not correctly understanding the expected return type or arguments of the `render` function.","error":"Argument of type '{ slots: SlotProps[]; }' is not assignable to parameter of type 'ReactNode'."}],"ecosystem":"npm"}