diff --git a/src/components/Input.tsx b/src/components/Input.tsx index b83de1a2..40ecccf8 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -9,6 +9,8 @@ interface InputProps extends TextInputProps { containerStyle?: ViewStyle; leftIcon?: React.ReactNode; rightIcon?: React.ReactNode; + /** React 19 passes `ref` as a prop; it reaches the TextInput (focus chaining). */ + ref?: React.Ref; } /** @@ -27,6 +29,7 @@ export default function Input({ leftIcon, rightIcon, style, + ref, ...props }: InputProps) { const c = useColors(); @@ -44,6 +47,7 @@ export default function Input({ ]}> {leftIcon && {leftIcon}} makeStyles(c), [c]); const t = useLocaleStore((s) => s.t); const [showPassword, setShowPassword] = React.useState(false); + // Return moves username → password → code, then signs in. + const passwordRef = React.useRef(null); + const totpRef = React.useRef(null); return ( @@ -63,6 +66,9 @@ export default function PasswordStep({ autoComplete="email" textContentType="username" keyboardType="email-address" + returnKeyType="next" + blurOnSubmit={false} + onSubmitEditing={() => passwordRef.current?.focus()} /> totpRef.current?.focus() : onSubmit} rightIcon={ setShowPassword((v) => !v)} - hitSlop={8} + hitSlop={14} accessibilityRole="button" accessibilityLabel={showPassword ? t('login.hide_password', 'Hide password') : t('login.show_password', 'Show password')} > @@ -93,6 +101,7 @@ export default function PasswordStep({ label={t('login.totp_label', 'Two-factor code')} placeholder="123456" value={totp} + ref={totpRef} onChangeText={(value) => onChangeTotp?.(value)} autoFocus keyboardType="number-pad"