Input

React Native

Error shake, focus ring and a drawn success check.

Preview

It works in Expo and in bare React Native. New to beUI Native? Set up your app first.

$ bunx beui-native add input

Copies the component and the shared files it needs into src/, adds the theme tokens if they're missing, and installs its libraries. Files you've changed are kept.

Documentation

Native port of beUI Input. A text field with a label, leading and trailing icons, an error shake, and a check that draws itself on success.

import { Input } from "./src";

<Input
  label="Email"
  leftIcon={Mail}
  value={email}
  onChangeText={setEmail}
  error={valid ? undefined : "Enter a valid email address."}
  reserveErrorLine
/>
<Input label="Search" leftIcon={Search} success={found} />
<Input label="Password" secureTextEntry rightIcon={<ToggleButton />} />
  • Field: a 44-point, fully rounded field. Its border fades between idle, focused and error colours over 200 ms. Focus and error also show a 2-point ring, like the web's ring-2.
  • Error: a truthy error shakes the field (6, 4 and 2 points over 450 ms) and turns it red. A string error also shows a message that fades and drops in, and is announced to screen readers. reserveErrorLine keeps one line of space so content below doesn't jump.
  • Success: success draws a check at the trailing edge in place of rightIcon.
  • Icons: leftIcon and rightIcon take a component given { size, color } (such as a lucide icon) or a prebuilt element. A trailing control, such as a show-password button, sits in a 44-point square so it stays easy to tap.
  • State: pass value with onChangeText to control it, or defaultValue to let it manage itself. Every other TextInput prop passes through, and ref reaches the TextInput.
  • Accessibility: the label is the field's spoken name, and pressing the label focuses the field. The error message is read as the hint and reported as invalid.
  • Reduced motion: when the system asks for it, or disableAnimation is set, colours change instantly, nothing shakes, and the check appears fully drawn.

classNames styles the root, label, field, input and error message individually.

Keyboard

  • Theme: the keyboard follows the app's light or dark theme on iOS. Pass keyboardAppearance to override it.
  • Text: text and placeholder sit centred in the 44-point field on every platform. The field sets a font size without a line height, because a line height on a TextInput pushes the text down on iOS.
  • Moving between fields: ref reaches the TextInput, so set returnKeyType="next", submitBehavior="submit" and onSubmitEditing={() => nextRef.current?.focus()}.
  • Autofill: pass autoComplete and textContentType so iOS and Android can fill passwords, emails and one-time codes.
  • Staying above the keyboard: that's the screen's job, not the field's. Since Android became edge-to-edge, the window no longer resizes when the keyboard opens, so use react-native-keyboard-controller: wrap the app in KeyboardProvider, put forms in a KeyboardAwareScrollView with a bottomOffset, and add KeyboardToolbar for previous, next and done controls. The example app does exactly this.

Copy this directory, hooks/use-presence.ts, hooks/use-reduced-motion.ts, hooks/use-shake.ts, primitives/drawn-path.tsx, primitives/render-icon.tsx, styles/motion.ts, and the semantic tokens in styles/theme.css.

Also on the web. The React version of Input, built with Motion and Tailwind CSS.