OTP Input
tetra-ui/otp-inputFreeComponent
A component for entering one-time passwords with individual character slots.
Live preview
live · rendered by the registry
Rendered by tetra-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://tetra-ui.com/r/otp-input.jsonSource
1import { cva } from "class-variance-authority";2import {3 createContext,4 useCallback,5 useContext,6 useEffect,7 useImperativeHandle,8 useMemo,9 useRef,10 useState,11} from "react";12import {13 type BlurEvent,14 type FocusEvent,15 Pressable,16 type TextInput as RNTextInput,17 View,18} from "react-native";19import Animated, {20 FadeIn,21 FadeOut,22 FlipInXDown,23 FlipOutXDown,24 useAnimatedStyle,25 useSharedValue,26 withRepeat,27 withTiming,28} from "react-native-reanimated";29import { cn } from "../lib/utils";30import { Input } from "./input";31import { Text } from "./text";3233// Constants34const CARET_ANIMATION_DURATION = 500;35const SLOT_VALUE_ENTER_DURATION = 250;36const SLOT_VALUE_EXIT_DURATION = 100;3738export const REGEXP_ONLY_DIGITS = "^\\d+$";39export const REGEXP_ONLY_CHARS = "^[a-zA-Z]+$";40export const REGEXP_ONLY_DIGITS_AND_CHARS = "^[a-zA-Z0-9]+$";4142const AnimatedText = Animated.createAnimatedComponent(Text);4344// Types45type SlotData = {46 index: number;47 char: string | null;48 placeholderChar: string | null;49 isActive: boolean;50 isCaretVisible: boolean;51};5253type OTPInputContextValue = {54 value: string;55 maxLength: number;56 isFocused: boolean;57 disabled?: boolean;58 invalid?: boolean;59 secureTextEntry?: boolean;60 slots: SlotData[];61 inputRef: React.RefObject<RNTextInput | null>;62 focus: () => void;63 onSlotPress: (index: number) => void;64};6566type OTPInputSlotContextValue = {67 slot: SlotData;68 isActive: boolean;69 isCaretVisible: boolean;70};7172export type OTPInputRef = {73 focus: () => void;74 blur: () => void;75 clear: () => void;76 setValue: (value: string) => void;77};7879export type OTPInputProps = {80 maxLength: number;81 value?: string;82 defaultValue?: string;83 onValueChange?: (value: string) => void;84 onComplete?: (value: string) => void;85 disabled?: boolean;86 invalid?: boolean;87 pattern?: string;88 inputMode?: React.ComponentProps<typeof RNTextInput>["inputMode"];89 placeholder?: string;90 secureTextEntry?: boolean;91 onFocus?: (e: FocusEvent) => void;92 onBlur?: (e: BlurEvent) => void;93 className?: string;94 children?: React.ReactNode;95 ref?: React.RefObject<OTPInputRef>;96};9798export type OTPInputGroupProps = React.ComponentProps<typeof View>;99100export type OTPInputSlotProps = React.ComponentProps<typeof Pressable> & {101 index: number;102 children?: React.ReactNode;103};104105export type OTPInputSeparatorProps = React.ComponentProps<typeof View>;106107export type OTPInputSlotPlaceholderProps = React.ComponentProps<typeof Text> & {108// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from tetra-ui
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | tetra-ui | Components | Free | 1 dep | |
| Action Inputaction-input | tetra-ui | Components | Free | no deps | |
| Alertalert | tetra-ui | Components | Free | no deps | |
| Avataravatar | tetra-ui | Components | Free | no deps | |
| Badgebadge | tetra-ui | Components | Free | no deps | |
| Bottom Sheetbottom-sheet | tetra-ui | Components | Free | 4 deps · 7 files | |
| Buttonbutton | tetra-ui | Components | Free | no deps | |
| Cardcard | tetra-ui | Components | Free | no deps |
