Input OTP

The InputOtp component allows users to enter one-time passcodes. It provides a series of input boxes that automatically handle focus and input.

Installation

$ cbui-cli install inputotp

Import

index.tsx
1import { InputOtp } from '@/crossbuildui/inputotp';

InputOtp Component

Basic Usage

Specify the length of the OTP.

MyComponent.tsx
1<InputOtp length={6} />

Variants

InputOtp supports multiple visual variant options for the input boxes: flat, bordered (default), faded, underlined, and glass.

MyComponent.tsx
1<View style={{gap: 16}}> 2 <InputOtp length={4} variant="flat" /> 3 <InputOtp length={4} variant="bordered" /> {/* Default */} 4 <InputOtp length={4} variant="faded" /> 5 <InputOtp length={4} variant="underlined" /> 6 <InputOtp length={4} variant="glass" /> 7</View>

Sizes

Adjust input box size with sm, md (default), or lg.

MyComponent.tsx
1<View style={{gap: 16, alignItems: 'center'}}> 2 <InputOtp length={4} size="sm" /> 3 <InputOtp length={4} size="md" /> {/* Default */} 4 <InputOtp length={4} size="lg" /> 5</View>

Radius

Control the border radius of input boxes with none, sm, md (default), lg, or full.

MyComponent.tsx
1<View style={{gap: 16, alignItems: 'center'}}> 2 <InputOtp length={4} radius="none" /> 3 <InputOtp length={4} radius="sm" /> 4 <InputOtp length={4} radius="md" /> {/* Default */} 5 <InputOtp length={4} radius="lg" /> 6 <InputOtp length={4} radius="full" /> 7</View>

Colors

The color prop influences the input box appearance on focus or when invalid. Supported colors include primary, secondary, success, warning, danger, and default.

MyComponent.tsx
1<View style={{gap: 16, alignItems: 'center'}}> 2 <InputOtp length={4} color="primary" placeholder="P" /> 3 <InputOtp length={4} color="secondary" placeholder="S" /> 4 <InputOtp length={4} color="success" placeholder="S" /> 5 <InputOtp length={4} color="warning" placeholder="W" /> 6 <InputOtp length={4} color="danger" isInvalid errorMessage="Invalid OTP" /> 7 <InputOtp length={4} color="default" placeholder="D" /> 8</View>

Glass Variant

The glass variant applies a frosted glass effect to each OTP input box background using expo-blur. Customize its appearance with glassIntensity (0-100) and glassTint ('light', 'dark', or 'default'). Text and placeholder colors for this variant typically adapt to the theme's foreground color for better contrast. The border color also adapts based on focus, invalid state, and glass tint.

MyComponent.tsx
1<View style={{gap: 16}}> 2 <InputOtp 3 length={4} 4 variant="glass" 5 glassIntensity={70} 6 glassTint="light" 7 placeholder="LGT" 8 /> 9 <InputOtp 10 length={6} 11 variant="glass" 12 glassIntensity={40} 13 glassTint="dark" 14 placeholder="DRK" 15 /> 16</View>

Description and Error Message

Provide helpful context with description or display validation feedback using isInvalid and errorMessage.

MyComponent.tsx
1<View style={{gap: 16}}> 2 <InputOtp 3 length={6} 4 description="Enter the 6-digit code sent to your phone." 5 /> 6 <InputOtp 7 length={4} 8 isInvalid 9 errorMessage="The OTP entered is incorrect. Please try again." 10 value="123" // Example value to show error state 11 /> 12</View>

Controlled and Uncontrolled

Manage OTP state externally using value and onValueChange for a controlled component, or let it manage its own state (uncontrolled).

MyComponent.tsx
1// Controlled InputOtp 2function ControlledInputOtpExample() { 3 const [otp, setOtp] = React.useState(''); 4 5 return ( 6 <View style={{gap: 8}}> 7 <InputOtp 8 length={4} 9 value={otp} 10 onValueChange={setOtp} 11 placeholder="C" 12 /> 13 <Text>Current OTP: {otp}</Text> 14 </View> 15 ); 16} 17 18// Uncontrolled InputOtp (uses internal state) 19// <InputOtp length={4} placeholder="U" /> 20

Disabled State

Disable the OTP input using the disabled prop.

MyComponent.tsx
1<InputOtp length={4} disabled value="1234" />

Placeholder

Set a placeholder character for empty input boxes and customize its color with placeholderTextColor.

MyComponent.tsx
1<View style={{gap: 16}}> 2 <InputOtp length={4} placeholder="0" /> 3 <InputOtp length={4} placeholder="*" placeholderTextColor="blue" /> 4</View>

Custom TextInput Props

Pass additional props to the underlying TextInput components using textInputProps. This is useful for settings like keyboardType, autoFocus on the first input, etc.

MyComponent.tsx
1<InputOtp 2 length={6} 3 textInputProps={{ 4 keyboardType: 'default', // Default is 'number-pad' 5 // You can pass other TextInput props like autoFocus on the first input, etc. 6 // Note: some props like 'value', 'onChangeText', 'maxLength' are controlled by InputOtp 7 }} 8 description="Uses 'default' keyboard type." 9/>

Props Overview

PROPTYPEDEFAULTDESCRIPTION
lengthnumber-Number of OTP input boxes. Required.
variantInputOtpVariant'bordered'Visual style.
colorInputOtpColor'default'Thematic color on focus/invalid.
sizeInputOtpSize'md'Size of input boxes.
radiusInputOtpRadius'md'Border radius of boxes.
valuestring-Controlled value of the OTP.
onValueChange(otp: string) => void-Callback when OTP value changes.
descriptionReactNode-Helper text below the OTP input.
errorMessageReactNode-Error message when isInvalid.
isInvalidbooleanfalseMarks input as invalid.
stylesInputOtpSlotsStyles-Custom styles for slots (base, otpInputWrapper, etc.).
styleStyleProp<ViewStyle>-Style for the outermost container (styles.base equivalent).
disabledbooleanfalseDisable the input.
placeholderstring-Placeholder character for each box.
placeholderTextColorColorValue-Custom color for placeholder text.
textInputPropsOmit<TextInputProps, ...>-Props for underlying TextInput components.
glassTint'default' | 'light' | 'dark'Theme-derivedTint for the 'glass' variant blur effect on each input box.
glassIntensitynumber30Intensity (0-100) for the 'glass' variant blur effect.

Styling

Customize the InputOtp appearance using the style prop for the main wrapper or the styles prop for more granular control over internal slots:

  • style: Applied to the outermost container (View) of the entire component. Equivalent to styles.base.
  • styles.base: Styles for the outermost container.
  • styles.otpInputWrapper: Styles for the View that wraps all the individual OTP input boxes.
  • styles.otpInput: Styles for each individual OTP TextInput box.
  • styles.description: Styles for the description Text component.
  • For the glass variant, each otpInput box background is rendered by BlurView from expo-blur, controlled by glassIntensity and glassTint. The styles.otpInput.backgroundColor will be overridden for this variant.
  • styles.errorMessage: Styles for the error message Text component.
MyComponent.tsx
1<InputOtp 2 length={4} 3 value="STYL" 4 style={{ marginVertical: 20, padding: 10, backgroundColor: '#e6e6fa' }} // Styles the outermost 'base' container 5 styles={{ 6 base: { borderWidth: 1, borderColor: 'purple' }, 7 otpInputWrapper: { columnGap: 20 }, // Increased gap between boxes 8 otpInput: { 9 backgroundColor: 'lightcyan', 10 borderColor: 'teal', 11 borderWidth: 2, 12 color: 'darkgreen', 13 fontWeight: 'bold', 14 }, 15 description: { color: 'navy', fontStyle: 'italic', marginTop: 10 }, 16 errorMessage: { color: 'darkred', fontWeight: 'bold', marginTop: 10 } 17 }} 18 description="This OTP input has custom slot styling." 19/>

Accessibility

The InputOtp component includes features to aid accessibility:

  • Each input box has textContentType="oneTimeCode" (iOS) and autoComplete="sms-otp" (Android) / "one-time-code" (web) to help with autofill from SMS.
  • Keyboard type defaults to "number-pad" for easier numeric input.
  • Consider providing an overall accessibilityLabel for the component if the context isn't clear from surrounding elements, especially if there's no visible description.