diff --git a/src/components/forms/DateField/index.android.tsx b/src/components/forms/DateField/index.android.tsx
index a6b6993dca..3be555238b 100644
--- a/src/components/forms/DateField/index.android.tsx
+++ b/src/components/forms/DateField/index.android.tsx
@@ -1,4 +1,5 @@
-import React from 'react'
+import {useCallback, useImperativeHandle, useState} from 'react'
+import {Keyboard} from 'react-native'
import DatePicker from 'react-native-date-picker'
import {useTheme} from '#/alf'
@@ -12,6 +13,7 @@ export const LabelText = TextField.LabelText
export function DateField({
value,
+ inputRef,
onChangeDate,
label,
isInvalid,
@@ -20,9 +22,9 @@ export function DateField({
maximumDate,
}: DateFieldProps) {
const t = useTheme()
- const [open, setOpen] = React.useState(false)
+ const [open, setOpen] = useState(false)
- const onChangeInternal = React.useCallback(
+ const onChangeInternal = useCallback(
(date: Date) => {
setOpen(false)
@@ -32,11 +34,25 @@ export function DateField({
[onChangeDate, setOpen],
)
- const onPress = React.useCallback(() => {
+ useImperativeHandle(
+ inputRef,
+ () => ({
+ focus: () => {
+ Keyboard.dismiss()
+ setOpen(true)
+ },
+ blur: () => {
+ setOpen(false)
+ },
+ }),
+ [],
+ )
+
+ const onPress = useCallback(() => {
setOpen(true)
}, [])
- const onCancel = React.useCallback(() => {
+ const onCancel = useCallback(() => {
setOpen(false)
}, [])
diff --git a/src/components/forms/DateField/index.tsx b/src/components/forms/DateField/index.tsx
index eca4d5cbd5..b8ecf2e6f5 100644
--- a/src/components/forms/DateField/index.tsx
+++ b/src/components/forms/DateField/index.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import {useCallback, useImperativeHandle} from 'react'
import {Keyboard, View} from 'react-native'
import DatePicker from 'react-native-date-picker'
import {msg, Trans} from '@lingui/macro'
@@ -25,6 +25,7 @@ export const LabelText = TextField.LabelText
*/
export function DateField({
value,
+ inputRef,
onChangeDate,
testID,
label,
@@ -36,7 +37,7 @@ export function DateField({
const t = useTheme()
const control = Dialog.useDialogControl()
- const onChangeInternal = React.useCallback(
+ const onChangeInternal = useCallback(
(date: Date | undefined) => {
if (date) {
const formatted = toSimpleDateString(date)
@@ -46,6 +47,20 @@ export function DateField({
[onChangeDate],
)
+ useImperativeHandle(
+ inputRef,
+ () => ({
+ focus: () => {
+ Keyboard.dismiss()
+ control.open()
+ },
+ blur: () => {
+ control.close()
+ },
+ }),
+ [control],
+ )
+
return (
<>
}
label={label}
onChange={handleOnChange}
- onChangeText={() => {}}
testID={testID}
accessibilityHint={accessibilityHint}
// @ts-expect-error not typed as even though it is one
diff --git a/src/components/forms/DateField/types.ts b/src/components/forms/DateField/types.ts
index 1784b884fb..560d780b4a 100644
--- a/src/components/forms/DateField/types.ts
+++ b/src/components/forms/DateField/types.ts
@@ -1,7 +1,12 @@
+export type DateFieldRef = {
+ focus: () => void
+ blur: () => void
+}
export type DateFieldProps = {
value: string | Date
onChangeDate: (date: string) => void
label: string
+ inputRef?: React.Ref
isInvalid?: boolean
testID?: string
accessibilityHint?: string
diff --git a/src/screens/Signup/StepInfo/index.tsx b/src/screens/Signup/StepInfo/index.tsx
index 4ad899864d..18ba385288 100644
--- a/src/screens/Signup/StepInfo/index.tsx
+++ b/src/screens/Signup/StepInfo/index.tsx
@@ -1,5 +1,5 @@
import React, {useRef} from 'react'
-import {View} from 'react-native'
+import {TextInput, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import * as EmailValidator from 'email-validator'
@@ -11,8 +11,9 @@ import {logger} from '#/logger'
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
import {is13, is18, useSignupContext} from '#/screens/Signup/state'
import {Policies} from '#/screens/Signup/StepInfo/Policies'
-import {atoms as a} from '#/alf'
+import {atoms as a, native} from '#/alf'
import * as DateField from '#/components/forms/DateField'
+import {DateFieldRef} from '#/components/forms/DateField/types'
import {FormError} from '#/components/forms/FormError'
import {HostingProvider} from '#/components/forms/HostingProvider'
import * as TextField from '#/components/forms/TextField'
@@ -51,6 +52,10 @@ export function StepInfo({
const prevEmailValueRef = useRef(state.email)
const passwordValueRef = useRef(state.password)
+ const emailInputRef = useRef(null)
+ const passwordInputRef = useRef(null)
+ const birthdateInputRef = useRef(null)
+
const [hasWarnedEmail, setHasWarnedEmail] = React.useState(false)
const tldtsRef = React.useRef()
@@ -155,6 +160,11 @@ export function StepInfo({
autoCapitalize="none"
autoComplete="email"
keyboardType="email-address"
+ returnKeyType="next"
+ submitBehavior={native('submit')}
+ onSubmitEditing={native(() =>
+ emailInputRef.current?.focus(),
+ )}
/>
@@ -167,6 +177,7 @@ export function StepInfo({
{
emailValueRef.current = value.trim()
if (hasWarnedEmail) {
@@ -178,6 +189,11 @@ export function StepInfo({
autoCapitalize="none"
autoComplete="email"
keyboardType="email-address"
+ returnKeyType="next"
+ submitBehavior={native('submit')}
+ onSubmitEditing={native(() =>
+ passwordInputRef.current?.focus(),
+ )}
/>
@@ -189,6 +205,7 @@ export function StepInfo({
{
passwordValueRef.current = value
}}
@@ -197,6 +214,11 @@ export function StepInfo({
secureTextEntry
autoComplete="new-password"
autoCapitalize="none"
+ returnKeyType="next"
+ submitBehavior={native('blurAndSubmit')}
+ onSubmitEditing={native(() =>
+ birthdateInputRef.current?.focus(),
+ )}
/>
@@ -206,6 +228,7 @@ export function StepInfo({
{
dispatch({