mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-04 16:06:41 +00:00
fix: move from username to password to code with the return key when signing in
This commit is contained in:
@@ -9,6 +9,8 @@ interface InputProps extends TextInputProps {
|
|||||||
containerStyle?: ViewStyle;
|
containerStyle?: ViewStyle;
|
||||||
leftIcon?: React.ReactNode;
|
leftIcon?: React.ReactNode;
|
||||||
rightIcon?: React.ReactNode;
|
rightIcon?: React.ReactNode;
|
||||||
|
/** React 19 passes `ref` as a prop; it reaches the TextInput (focus chaining). */
|
||||||
|
ref?: React.Ref<RNTextInput>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,6 +29,7 @@ export default function Input({
|
|||||||
leftIcon,
|
leftIcon,
|
||||||
rightIcon,
|
rightIcon,
|
||||||
style,
|
style,
|
||||||
|
ref,
|
||||||
...props
|
...props
|
||||||
}: InputProps) {
|
}: InputProps) {
|
||||||
const c = useColors();
|
const c = useColors();
|
||||||
@@ -44,6 +47,7 @@ export default function Input({
|
|||||||
]}>
|
]}>
|
||||||
{leftIcon && <View style={styles.iconLeft}>{leftIcon}</View>}
|
{leftIcon && <View style={styles.iconLeft}>{leftIcon}</View>}
|
||||||
<RNTextInput
|
<RNTextInput
|
||||||
|
ref={ref}
|
||||||
{...props}
|
{...props}
|
||||||
style={[styles.input, style]}
|
style={[styles.input, style]}
|
||||||
placeholderTextColor={c.textMuted}
|
placeholderTextColor={c.textMuted}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, Pressable, StyleSheet } from 'react-native';
|
import { View, Text, Pressable, StyleSheet, type TextInput } from 'react-native';
|
||||||
import { Eye, EyeOff } from 'lucide-react-native';
|
import { Eye, EyeOff } from 'lucide-react-native';
|
||||||
import { spacing, typography, type ThemePalette } from '../../theme/tokens';
|
import { spacing, typography, type ThemePalette } from '../../theme/tokens';
|
||||||
import { useColors } from '../../theme/colors';
|
import { useColors } from '../../theme/colors';
|
||||||
@@ -43,6 +43,9 @@ export default function PasswordStep({
|
|||||||
const styles = React.useMemo(() => makeStyles(c), [c]);
|
const styles = React.useMemo(() => makeStyles(c), [c]);
|
||||||
const t = useLocaleStore((s) => s.t);
|
const t = useLocaleStore((s) => s.t);
|
||||||
const [showPassword, setShowPassword] = React.useState(false);
|
const [showPassword, setShowPassword] = React.useState(false);
|
||||||
|
// Return moves username → password → code, then signs in.
|
||||||
|
const passwordRef = React.useRef<TextInput>(null);
|
||||||
|
const totpRef = React.useRef<TextInput>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.root}>
|
<View style={styles.root}>
|
||||||
@@ -63,6 +66,9 @@ export default function PasswordStep({
|
|||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
textContentType="username"
|
textContentType="username"
|
||||||
keyboardType="email-address"
|
keyboardType="email-address"
|
||||||
|
returnKeyType="next"
|
||||||
|
blurOnSubmit={false}
|
||||||
|
onSubmitEditing={() => passwordRef.current?.focus()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
@@ -74,12 +80,14 @@ export default function PasswordStep({
|
|||||||
secureTextEntry={!showPassword}
|
secureTextEntry={!showPassword}
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
textContentType="password"
|
textContentType="password"
|
||||||
|
ref={passwordRef}
|
||||||
returnKeyType={totpRequired ? 'next' : 'go'}
|
returnKeyType={totpRequired ? 'next' : 'go'}
|
||||||
onSubmitEditing={totpRequired ? undefined : onSubmit}
|
blurOnSubmit={!totpRequired}
|
||||||
|
onSubmitEditing={totpRequired ? () => totpRef.current?.focus() : onSubmit}
|
||||||
rightIcon={
|
rightIcon={
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={() => setShowPassword((v) => !v)}
|
onPress={() => setShowPassword((v) => !v)}
|
||||||
hitSlop={8}
|
hitSlop={14}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={showPassword ? t('login.hide_password', 'Hide password') : t('login.show_password', 'Show password')}
|
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')}
|
label={t('login.totp_label', 'Two-factor code')}
|
||||||
placeholder="123456"
|
placeholder="123456"
|
||||||
value={totp}
|
value={totp}
|
||||||
|
ref={totpRef}
|
||||||
onChangeText={(value) => onChangeTotp?.(value)}
|
onChangeText={(value) => onChangeTotp?.(value)}
|
||||||
autoFocus
|
autoFocus
|
||||||
keyboardType="number-pad"
|
keyboardType="number-pad"
|
||||||
|
|||||||
Reference in New Issue
Block a user