# Input & OtpInput (React Native)

> Text fields with label, hint and error, clear and reveal buttons, a character count, and a one-time-code input that fills from SMS.

GramproKit for React Native · Forms · Beta · Source: https://kit.gramproindia.com/native/docs/input

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/input). The example's source:

```tsx
import { useState } from "react";
import { Text } from "react-native";
import { Input, OtpInput } from "@/component-lib/input";
import { useKitTheme } from "@/component-lib/shared/native";
import { Section } from "./layout"; // Section and Row: page layout for the demo

export function InputDemo() {
  const { tokens } = useKitTheme();
  const [code, setCode] = useState("");
  const [done, setDone] = useState<string | null>(null);
  return (
    <>
      <Section title="Input · basics">
        <Input label="Full name" placeholder="Anand Remanan" clearable defaultValue="Anand" />
        <Input
          label="Email"
          type="email"
          placeholder="you@example.com"
          description="We never share it."
          required
        />
        <Input label="Password" type="password" defaultValue="hunter22" />
        <Input
          label="Website"
          type="url"
          leading="https://"
          placeholder="gramproindia.com"
        />
        <Input label="Weight" type="number" trailing="kg" defaultValue="72.5" />
      </Section>

      <Section title="Input · states">
        <Input label="Bio" showCount maxLength={20} defaultValue="Builds 👨‍👩‍👧 UI kits" />
        <Input label="PAN" defaultValue="ABCDE1234" error="PAN has 10 characters." />
        <Input label="Read only" readOnly defaultValue="INV-2026-0042" />
        <Input label="Disabled" disabled defaultValue="Can't touch this" />
        <Input size="sm" placeholder="Small" />
        <Input size="lg" placeholder="Large" />
      </Section>

      <Section title="OtpInput">
        <OtpInput
          label="Verification code"
          description="Sent to +91 98xxx xx210. Paste the whole SMS to fill it."
          value={code}
          onValueChange={setCode}
          onComplete={setDone}
        />
        {done ? <Text style={{ color: tokens.success }}>Completed: {done}</Text> : null}
        <OtpInput label="Grouped, masked" length={6} groups={[3, 3]} mask defaultValue="123" />
        <OtpInput label="Alphanumeric" length={4} mode="alphanumeric" uppercase error="Code expired." />
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add Input
```

## Usage

```tsx
import { Input, OtpInput } from "@/component-lib/input";

<Input label="Email" type="email" required description="We never share it." />
<OtpInput label="Verification code" length={6} onComplete={verify} />
```

## Props

### InputProps

| Prop | Type | Description |
|---|---|---|
| `value` | `string` |   |
| `defaultValue` | `string` |   |
| `onValueChange` | `(value: string) => void` | The new text on every change. `onChangeText` fires as well. |
| `type` | `InputType` | Picks the keyboard, autofill and secure entry, as `type` does on the web. Default `text`. |
| `label` | `ReactNode` | The field's name, shown above it. |
| `description` | `ReactNode` | A hint under the field, read as the field's hint. |
| `error` | `ReactNode` | Message below the field; also marks it invalid. |
| `size` | `FieldSize` | Default `md`. |
| `leading` | `ReactNode` | Content before the text, e.g. an icon or "https://". |
| `trailing` | `ReactNode` | Content after the text, e.g. a unit such as "kg". |
| `clearable` | `boolean` | A button that empties the field. Default false. |
| `revealPassword` | `boolean` | For `type="password"`, a button that shows the text. Default true. |
| `showCount` | `boolean` | A character counter under the field; shows `count / maxLength` when `maxLength` is set. |
| `disabled` | `boolean` |   |
| `readOnly` | `boolean` |   |
| `required` | `boolean` | Marks the label with an asterisk. Native has no form validation of its own. |
| `style` | `Styleable<ViewStyle>` |   |
| `styles` | `Partial<{ root: Styleable<ViewStyle>; label: Styleable<TextStyle>; control: Styleable<V…` |   |
| `localeText` | `Partial<InputLocaleText>` |   |

Also accepts the props of `Omit<TextInputProps, "value" | "defaultValue" | "style" | "editable" | "secureTextEntry">`.

### OtpInputProps

| Prop | Type | Description |
|---|---|---|
| `length` | `number` | Number of characters. Default 6. |
| `mode` | `OtpMode` | Default `numeric`. |
| `uppercase` | `boolean` | Turn letters into capitals as they are typed. |
| `value` | `string` |   |
| `defaultValue` | `string` |   |
| `onValueChange` | `(value: string) => void` |   |
| `onComplete` | `(value: string) => void` | Every cell is filled. |
| `groups` | `number[]` | Group sizes with a separator between them, e.g. `[3, 3]`. |
| `mask` | `boolean` | Show dots instead of the characters. |
| `label` | `ReactNode` |   |
| `description` | `ReactNode` |   |
| `error` | `ReactNode` |   |
| `size` | `FieldSize` |   |
| `disabled` | `boolean` |   |
| `readOnly` | `boolean` |   |
| `required` | `boolean` |   |
| `style` | `Styleable<ViewStyle>` |   |
| `styles` | `Partial<{ root: Styleable<ViewStyle>; label: Styleable<TextStyle>; cells: Styleable<Vie…` |   |
| `localeText` | `Partial<InputLocaleText>` |   |

Also accepts the props of `Omit< TextInputProps, "value" | "defaultValue" | "style" | "editable" | "maxLength" | "keyboardType" | "inputMode" | "secureTextEntry" >`.

## Native and web

- `type` picks the keyboard, autofill and secure entry. `onChangeText` fires alongside `onValueChange`.
- OtpInput is one real TextInput under drawn cells, so paste and SMS autofill (`oneTimeCode`, `sms-otp`) fill every cell.
- `description` and `error` become the accessibility hint; errors are announced.
- Web version: [Input & OtpInput on the web](https://kit.gramproindia.com/input).
