chahinebrini f24c364c81 feat(rebreak-native): KeyboardAwareScreen composable + full-screen form migration (phase 3A)
New component/KeyboardAwareScreen.tsx encapsulates the standard
KeyboardAvoidingView pattern for full-screen forms:
- iOS behavior="padding", Android no-op (adjustResize covers it)
- scrollable prop: ScrollView with keyboardShouldPersistTaps="handled"
- non-scrollable: TouchableWithoutFeedback+View for tap-to-dismiss
- headerOffset prop for screens owning their own header padding

Migrated to KeyboardAwareScreen: signin, signup, forgot-password,
confirm-otp (SafeAreaView-wrapped, no headerOffset needed) and
profile/edit (KAV wrapper only, explicit ScrollView retained).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:12:29 +02:00

66 lines
2.0 KiB
TypeScript

import { ReactNode } from 'react';
import {
Keyboard,
KeyboardAvoidingView,
Platform,
ScrollView,
StyleProp,
TouchableWithoutFeedback,
View,
ViewStyle,
} from 'react-native';
export interface KeyboardAwareScreenProps {
children: ReactNode;
/**
* Extra offset for `keyboardVerticalOffset` on iOS. For screens wrapped in
* `<SafeAreaView>` this should be 0 (default) — the SafeAreaView already
* absorbs the top inset. For screens that own their header with
* `paddingTop: insets.top` baked in (e.g. profile/edit), pass the full
* header height so iOS computes the correct push distance.
*/
headerOffset?: number;
/**
* When true, wraps children in a `ScrollView`. Use for long forms (sign-up,
* profile-edit). When false (default), a plain `View` fills the remaining
* space — tap anywhere outside an input dismisses the keyboard.
*/
scrollable?: boolean;
/** Style applied to the outer KeyboardAvoidingView. */
style?: StyleProp<ViewStyle>;
/** Style applied to the inner container (ScrollView or View). */
contentContainerStyle?: StyleProp<ViewStyle>;
}
export function KeyboardAwareScreen({
children,
headerOffset = 0,
scrollable = false,
style,
contentContainerStyle,
}: KeyboardAwareScreenProps) {
return (
<KeyboardAvoidingView
style={[{ flex: 1 }, style]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerOffset}
>
{scrollable ? (
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={contentContainerStyle}
keyboardShouldPersistTaps="handled"
keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}
showsVerticalScrollIndicator={false}
>
{children}
</ScrollView>
) : (
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={[{ flex: 1 }, contentContainerStyle]}>{children}</View>
</TouchableWithoutFeedback>
)}
</KeyboardAvoidingView>
);
}