Skip to content
Native Animation
Floating Label Input animation preview
Micro

Floating Label Input

A polished 56-point text field with a spring-driven label, touch-origin focus light, blurred validation feedback, and drawn status icons.

$9 for this animation

Checkout opens soon. Leave your email and we will tell you the moment you can buy it.

One email when checkout opens. No spam.

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

npx nativeanimation add floating-label-input

About this animation

A polished 56-point text field with a spring-driven label, touch-origin focus light, blurred validation feedback, and drawn status icons.

How it works

  1. Focus and content feed one label progress value; an interruptible spring moves, shrinks, and recolors the label.
  2. onTouchStart records the exact contact point. Four thin light segments grow toward the corners so the accent border appears to ignite from that point.
  3. Validation messages reveal their layout while fading, translating, and sharpening from a 4-point blur.
  4. Valid and invalid states draw a check or alert from timed View strokes, without an icon dependency.
  5. Controlled and uncontrolled values share the same input path, while an imperative ref exposes focus, blur, and clear.

Why this one

Most floating-label fields only move a label and swap a border color. This version coordinates touch position, spring typography, live feedback, a drawn status glyph, reduced motion, dark mode, and layered surface depth. The result communicates focus and validation immediately without turning a routine form control into decoration.

Install

npx expo install expo-linear-gradient react-native-reanimated

Usage

import { useState } from 'react';
import FloatingLabelInput from './FloatingLabelInput';

export function EmailField() {
  const [email, setEmail] = useState('');
  const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

  return (
    <FloatingLabelInput
      label="Email address"
      value={email}
      onChangeText={setEmail}
      error={email.length > 0 && !valid ? 'Enter a complete email address' : undefined}
      helperText={valid ? 'Email is ready' : undefined}
      validationState={email.length === 0 ? 'idle' : valid ? 'valid' : 'invalid'}
      inputProps={{ autoComplete: 'email', keyboardType: 'email-address' }}
    />
  );
}

Personality knobs can restyle the same interaction:

<FloatingLabelInput
  label="Project name"
  accentColor="#3366FF"
  successColor="#148060"
  height={60}
  maxLength={48}
  showCharacterCount
  colorScheme="dark"
/>

Props

PropTypeDefaultDescription
labelstringRequiredText that floats above the value.
valuestring—Controlled text value.
defaultValuestring''Initial uncontrolled value.
onChangeText(value: string) => void—Called whenever the value changes.
errorstring—Invalid-state message; takes precedence over validationState.
helperTextstring—Supporting or success message.
validationState'idle' | 'valid' | 'invalid''idle'Controls the drawn status glyph.
showCharacterCountbooleanfalseShows the current length.
maxLengthnumber—Native length limit and counter target.
heightnumber56Field height in points.
accentColorstring'#6E56FF'Focus label, light, and glow color.
borderColorstringTranslucent inkResting one-point border.
errorColorstring'#D94763'Invalid state color.
successColorstring'#168A69'Valid state color.
backgroundColorstring'#FFFFFF'Surface color.
textColorstring'#17151C'Input value color.
labelFontFamilystringSystemLabel and validation font.
inputFontFamilystringSystemInput value font.
colorScheme'light' | 'dark' | 'auto''auto'Surface appearance.
durationnumber220Base duration for non-spring transitions.
accessibilityLabelstringlabelScreen-reader label.
inputPropsTextInputProps—Additional native input props.
styleStyleProp<ViewStyle>—Outer container style.
testIDstring—Native input test identifier.

The ref exposes focus(), blur(), and clear().

Compatibility

  • Expo SDK 57, React Native 0.86, and Reanimated 4.5
  • iOS and Android bundles verified; device behavior is not yet verified
  • Web verified
  • Works in Expo Go

Accessibility

The native field exposes its label, disabled state, and invalid state. Validation updates use a polite live region, and the optional character count has a descriptive label. Reduced Motion removes springs, drawing sequences, blur, and the touch-origin reveal while preserving every state change.