Form

Forms are used to collect user input.

Pro component

Requires all-access to use the source code

Apple
Apple
1

Add the following dependencies to your project:

npx expo install react-native-keyboard-controller
2

Edit _layout.tsx:

Wrap the _layout.tsx in <KeyboardProvider> with the 2 boolean props of statusBarTranslucent and navigationBarTranslucent

~/app/_layout.tsx
    import '../global.css';
    import 'expo-dev-client';

    import { PortalHost } from '@rn-primitives/portal';
    import { StatusBar } from 'expo-status-bar';
+   import { KeyboardProvider } from 'react-native-keyboard-controller';   
    // YOUR_OTHER_IMPORTS

    import { useColorScheme, useInitialAndroidBarSync } from '~/lib/useColorScheme';
    import { NAV_THEME } from '~/theme';

    export {    
      // Catch any errors thrown by the Layout component.
      ErrorBoundary,
    } from 'expo-router';

    export default function RootLayout() {    
      useInitialAndroidBarSync();
      const { colorScheme, isDarkColorScheme } = useColorScheme();
    
      return (
        <>
          <StatusBar
            key={`root-status-bar-${isDarkColorScheme ? 'light' : 'dark'}`}
            style={isDarkColorScheme ? 'light' : 'dark'}
          />
+         <KeyboardProvider statusBarTranslucent navigationBarTranslucent>
              <NavThemeProvider value={NAV_THEME[colorScheme]}>
                 {/* YOUR_ROOT_NAVIGATOR */}
                 <PortalHost />
              </NavThemeProvider>
+          </KeyboardProvider>
        </>
      );
    }
import { Stack } from 'expo-router';
import * as React from 'react';
import { Platform, View } from 'react-native';
import { KeyboardAwareScrollView, KeyboardGestureArea } from 'react-native-keyboard-controller';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

import { Button } from '../~/components/nativewindui/Button';
import { Form, FormItem, FormSection } from '~/components/nativewindui/Form';
import { Text } from '~/components/nativewindui/Text';
import { TextField } from '~/components/nativewindui/TextField';
import { cn } from '~/lib/cn';

export default function FormScreen() {
  const insets = useSafeAreaInsets();
  const [canSave, setCanSave] = React.useState(false);

  function onChange() {
    if (!canSave) {
      setCanSave(true);
    }
  }

  return (
    <>
      <Stack.Screen
        options={{
          title: 'Name',
          headerRight: Platform.select({
            ios: () => (
              <Button className="ios:px-0" disabled={!canSave} variant="plain">
                <Text className={cn(canSave && 'text-primary')}>Save</Text>
              </Button>
            ),
          }),
        }}
      />
      <KeyboardGestureArea interpolator="ios">
        <KeyboardAwareScrollView
          bottomOffset={8}
          keyboardShouldPersistTaps="handled"
          keyboardDismissMode="interactive"
          contentContainerStyle={{ paddingBottom: insets.bottom }}>
          <Form className="gap-5 px-4 pt-8">
            <FormSection materialIconProps={{ name: 'person-outline' }}>
              <FormItem>
                <TextField
                  textContentType="none"
                  autoComplete="off"
                  label={Platform.select({ ios: undefined, default: 'First' })}
                  leftView={Platform.select({ ios: <LeftLabel>First</LeftLabel> })}
                  placeholder={Platform.select({ ios: 'required' })}
                  onChange={onChange}
                />
              </FormItem>
              <FormItem>
                <TextField
                  textContentType="none"
                  autoComplete="off"
                  label={Platform.select({ ios: undefined, default: 'Middle' })}
                  leftView={Platform.select({ ios: <LeftLabel>Middle</LeftLabel> })}
                  placeholder={Platform.select({ ios: 'optional' })}
                  onChange={onChange}
                />
              </FormItem>
              <FormItem>
                <TextField
                  textContentType="none"
                  autoComplete="off"
                  label={Platform.select({ ios: undefined, default: 'Last' })}
                  leftView={Platform.select({ ios: <LeftLabel>Last</LeftLabel> })}
                  placeholder={Platform.select({ ios: 'required' })}
                  onChange={onChange}
                />
              </FormItem>
            </FormSection>
            {Platform.OS !== 'ios' && (
              <View className="items-end">
                <Button className="px-6">
                  <Text>Save</Text>
                </Button>
              </View>
            )}
          </Form>
        </KeyboardAwareScrollView>
      </KeyboardGestureArea>
    </>
  );
}

function LeftLabel({ children }: { children: string }) {
  return (
    <View className="w-28 justify-center pl-2">
      <Text>{children}</Text>
    </View>
  );
}
Logo

Unlock All Pro Screens & Components

Elevate your app with powerful, native-feeling components and templates. Build faster with beautiful ready-to-use designs.

Get all-access

Usage

The form component must be a child of a Scrollable component.

import { Form, FormItem, FormSection } from '~/components/nativewindui/Form';
<ScrollView contentContainerClassName="p-8">
  <Form>
    <FormSection>
      <FormItem>
        <TextInput
          placeholder="First Name"
          className="ios:border-0 border-border text-foreground rounded-lg border px-3 py-2.5 text-lg leading-6"
        />
      </FormItem>
      <FormItem>
        <TextInput
          placeholder="Last Name"
          className="ios:border-0 border-border text-foreground rounded-lg border px-3 py-2.5 text-lg leading-6"
        />
      </FormItem>
    </FormSection>
  </Form>
</ScrollView>

Props

Form

Inherits all the props from React Native's View component.

FormSection

Inherits all the props from React Native's View component.

PropTypeDescription
rootClassNamestringClass name for the root View component.
footnotestringText for the footnote at the bottom of the section.
footnoteClassNamestringClass name for styling the footnote.
ios{ title: string; titleClassName?: string }iOS-specific props including title and title class name.
materialIconPropsOmit<IconProps<'material'>, 'namingScheme' | 'ios'>Props for the Material Icon, excluding namingScheme and iOS-specific props.
styleViewStyleCustom style applied to the View component, defaults to BORDER_CURVE.

FormItem

Inherits all the props from React Native's View component.

PropTypeDescription
iosSeparatorClassNamestringClass name for styling the separator in iOS.
© Ronin Technologies LLC 2024