Skip to content

Commit 52d25f1

Browse files
authored
Fix/autofocusing (#1408)
* useConditionalAutofocus hook * allow password submission immediately if no errors * empty the mouth * increase timeout so that the styling isnt messed up, renaming, apply useEffect * tidy up, add back delay param
1 parent 472efbe commit 52d25f1

File tree

3 files changed

+67
-24
lines changed

3 files changed

+67
-24
lines changed

app/dash/Accounts/Add/Components/index.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
2-
import { useState, useRef } from 'react'
2+
import { useState } from 'react'
33

4+
import useFocusableRef from '../../../../../resources/Hooks/useFocusableRef'
45
import RingIcon from '../../../../../resources/Components/RingIcon'
56
import { ConfirmPassword, CreatePassword } from '../../../../../resources/Components/Password'
67
import link from '../../../../../resources/link'
@@ -18,7 +19,7 @@ const navForward = async (newAccountType, accountData) =>
1819

1920
const removeLineBreaks = (str) => str.replace(/(\r\n|\n|\r)/gm, '')
2021

21-
const AddHotAccountWrapper = ({ children, title, svgName, summary, intro, index }) => {
22+
const AddHotAccountWrapper = ({ children, title, svgName, summary, index }) => {
2223
return (
2324
<div className={'addAccountItem addAccountItemSmart addAccountItemAdding'}>
2425
<div className='addAccountItemBar addAccountItemHot' />
@@ -46,9 +47,9 @@ const AddHotAccountWrapper = ({ children, title, svgName, summary, intro, index
4647
)
4748
}
4849

49-
const EnterSecret = ({ newAccountType, validateSecret, title }) => {
50+
const EnterSecret = ({ newAccountType, validateSecret, title, autofocus }) => {
5051
const EMPTY_STATE = `Enter ${title}`
51-
const inputRef = useRef(null)
52+
const inputRef = useFocusableRef(autofocus, 100)
5253
const [error, setError] = useState(EMPTY_STATE)
5354

5455
const resetError = () => setError(EMPTY_STATE)
@@ -156,10 +157,10 @@ export function AddHotAccount({
156157
})
157158

158159
const steps = [
159-
<EnterSecret key={0} {...{ validateSecret, title, newAccountType }} />,
160-
<CreatePassword key={1} onCreate={onCreate} />,
161-
<ConfirmPassword key={2} password={password} onConfirm={onConfirm} />,
162-
<Error key={3} {...{ error }} />
160+
<EnterSecret key={0} {...{ validateSecret, title, newAccountType, autofocus: viewIndex === 0 }} />,
161+
<CreatePassword key={1} onCreate={onCreate} autofocus={viewIndex === 1} />,
162+
<ConfirmPassword key={2} password={password} onConfirm={onConfirm} autofocus={viewIndex === 2} />,
163+
<Error key={3} error={error} />
163164
]
164165

165166
return (

resources/Components/Password/index.js

+42-16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import React from 'react'
2-
import { useRef, useState } from 'react'
1+
import React, { useRef } from 'react'
2+
import { useState } from 'react'
33
import zxcvbn from 'zxcvbn'
4+
import useFocusableRef from '../../Hooks/useFocusableRef'
45

56
import { debounce } from '../../utils'
67

78
const NO_PASSWORD_ENTERED = 'Enter password'
89

9-
const PasswordInput = ({ getError, next, title, buttonText }) => {
10+
const PasswordInput = ({ getError: getInputError, next, title, buttonText, autofocus }) => {
1011
const [error, setError] = useState(NO_PASSWORD_ENTERED)
11-
const inputRef = useRef(null)
12+
const inputRef = useFocusableRef(autofocus)
13+
const [disabled, setDisabled] = useState(false)
1214

1315
const resetError = () => setError(NO_PASSWORD_ENTERED)
1416

@@ -22,12 +24,20 @@ const PasswordInput = ({ getError, next, title, buttonText }) => {
2224
setTimeout(clear, 600)
2325
}
2426

25-
const validateInput = debounce((e) => {
26-
const value = e.target.value
27-
if (!value) return resetError()
28-
const err = getError(value)
29-
setError(err || '')
30-
}, 300)
27+
const getError = () =>
28+
inputRef.current.value ? getInputError(inputRef.current.value) || '' : NO_PASSWORD_ENTERED
29+
30+
const validateInput = (e) => {
31+
const err = getError()
32+
if (err) {
33+
setDisabled(true)
34+
return debounce(() => {
35+
setDisabled(false)
36+
setError(getError())
37+
}, 300)()
38+
}
39+
return setError(err)
40+
}
3141

3242
return (
3343
<div className='addAccountItemOptionSetupFrame'>
@@ -42,7 +52,7 @@ const PasswordInput = ({ getError, next, title, buttonText }) => {
4252
ref={inputRef}
4353
onChange={validateInput}
4454
onKeyDown={(e) => {
45-
if (!error && e.key === 'Enter') handleSubmit()
55+
if (!error && e.key === 'Enter' && !disabled) handleSubmit()
4656
}}
4757
/>
4858
</div>
@@ -52,15 +62,15 @@ const PasswordInput = ({ getError, next, title, buttonText }) => {
5262
{error}
5363
</div>
5464
) : (
55-
<div role='button' className='addAccountItemOptionSubmit' onClick={() => handleSubmit()}>
65+
<div role='button' className='addAccountItemOptionSubmit' onClick={() => !disabled && handleSubmit()}>
5666
{buttonText}
5767
</div>
5868
)}
5969
</div>
6070
)
6171
}
6272

63-
export const CreatePassword = ({ onCreate }) => {
73+
export const CreatePassword = ({ onCreate, autofocus }) => {
6474
const getError = (password) => {
6575
if (password.length < 12) return 'PASSWORD MUST BE 12 OR MORE CHARACTERS'
6676
const {
@@ -72,13 +82,29 @@ export const CreatePassword = ({ onCreate }) => {
7282
return (warning || 'PLEASE ENTER A STRONGER PASSWORD').toUpperCase()
7383
}
7484

75-
return <PasswordInput getError={getError} next={onCreate} title='Create Password' buttonText='Continue' />
85+
return (
86+
<PasswordInput
87+
getError={getError}
88+
next={onCreate}
89+
title='Create Password'
90+
buttonText='Continue'
91+
autofocus={autofocus}
92+
/>
93+
)
7694
}
7795

78-
export const ConfirmPassword = ({ password, onConfirm }) => {
96+
export const ConfirmPassword = ({ password, onConfirm, autofocus }) => {
7997
const getError = (confirmedPassword) => {
8098
if (password !== confirmedPassword) return 'PASSWORDS DO NOT MATCH'
8199
}
82100

83-
return <PasswordInput getError={getError} next={onConfirm} title='Confirm Password' buttonText='Create' />
101+
return (
102+
<PasswordInput
103+
getError={getError}
104+
next={onConfirm}
105+
title='Confirm Password'
106+
buttonText='Create'
107+
autofocus={autofocus}
108+
/>
109+
)
84110
}

resources/Hooks/useFocusableRef.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useEffect, useRef } from 'react'
2+
3+
const useFocusableRef = (focus, delay = 900) => {
4+
const ref = useRef(null)
5+
6+
useEffect(() => {
7+
if (focus) {
8+
const timeout = setTimeout(() => ref.current && ref.current.focus(), delay)
9+
return () => clearTimeout(timeout)
10+
}
11+
})
12+
13+
return ref
14+
}
15+
16+
export default useFocusableRef

0 commit comments

Comments
 (0)