2
0

feat(inputs): improve input focus behavior

This commit is contained in:
Baptiste Arnaud
2022-08-14 17:53:53 +02:00
parent 008724a3b1
commit fd01793594
3 changed files with 39 additions and 32 deletions

View File

@ -17,7 +17,6 @@ export const SendButton = ({
}: SendButtonProps) => { }: SendButtonProps) => {
return ( return (
<button <button
type="submit"
disabled={isDisabled || isLoading} disabled={isDisabled || isLoading}
{...props} {...props}
className={ className={

View File

@ -6,10 +6,10 @@ import {
TextInputBlock, TextInputBlock,
UrlInputBlock, UrlInputBlock,
} from 'models' } from 'models'
import React, { FormEvent, useState } from 'react' import React, { useRef, useState } from 'react'
import { InputSubmitContent } from '../../InputChatBlock' import { InputSubmitContent } from '../../InputChatBlock'
import { SendButton } from '../SendButton' import { SendButton } from '../SendButton'
import { TextInput } from './TextInputContent' import { TextInput } from './TextInput'
type TextFormProps = { type TextFormProps = {
block: block:
@ -30,6 +30,7 @@ export const TextForm = ({
hasGuestAvatar, hasGuestAvatar,
}: TextFormProps) => { }: TextFormProps) => {
const [inputValue, setInputValue] = useState(defaultValue ?? '') const [inputValue, setInputValue] = useState(defaultValue ?? '')
const inputRef = useRef<HTMLInputElement | null>(null)
const isLongText = block.type === InputBlockType.TEXT && block.options?.isLong const isLongText = block.type === InputBlockType.TEXT && block.options?.isLong
@ -42,29 +43,41 @@ export const TextForm = ({
setInputValue(inputValue) setInputValue(inputValue)
} }
const handleSubmit = (e: FormEvent) => { const checkIfInputIsValid = () =>
e.preventDefault() inputValue !== '' && inputRef.current?.reportValidity()
if (inputValue === '') return
onSubmit({ value: inputValue }) const submit = () => {
if (checkIfInputIsValid()) onSubmit({ value: inputValue })
}
const submitWhenEnter = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') submit()
} }
return ( return (
<form <div
className="flex items-end justify-between rounded-lg pr-2 typebot-input w-full" className={
onSubmit={handleSubmit} 'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
}
data-testid="input" data-testid="input"
autoComplete={block.type === InputBlockType.TEXT ? 'off' : 'on'}
style={{ style={{
marginRight: hasGuestAvatar ? '50px' : '0.5rem', marginRight: hasGuestAvatar ? '50px' : '0.5rem',
maxWidth: isLongText ? undefined : '350px', maxWidth: isLongText ? undefined : '350px',
}} }}
onKeyDown={submitWhenEnter}
> >
<TextInput block={block} onChange={handleChange} value={inputValue} /> <TextInput
inputRef={inputRef}
block={block}
onChange={handleChange}
value={inputValue}
/>
<SendButton <SendButton
label={block.options?.labels?.button ?? 'Send'} label={block.options?.labels?.button ?? 'Send'}
isDisabled={inputValue === ''} isDisabled={inputValue === ''}
className="my-2 ml-2" className="my-2 ml-2"
onClick={submit}
/> />
</form> </div>
) )
} }

View File

@ -6,17 +6,11 @@ import {
UrlInputBlock, UrlInputBlock,
PhoneNumberInputBlock, PhoneNumberInputBlock,
} from 'models' } from 'models'
import React, { import React, { ChangeEvent, ChangeEventHandler } from 'react'
ChangeEvent,
ChangeEventHandler,
RefObject,
useEffect,
useRef,
} from 'react'
import PhoneInput, { Value, Country } from 'react-phone-number-input' import PhoneInput, { Value, Country } from 'react-phone-number-input'
import { isMobile } from 'services/utils'
type TextInputProps = { type TextInputProps = {
inputRef: React.RefObject<any>
block: block:
| TextInputBlock | TextInputBlock
| EmailInputBlock | EmailInputBlock
@ -27,13 +21,12 @@ type TextInputProps = {
onChange: (value: string) => void onChange: (value: string) => void
} }
export const TextInput = ({ block, value, onChange }: TextInputProps) => { export const TextInput = ({
const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null) inputRef,
block,
useEffect(() => { value,
setTimeout(() => inputRef.current?.focus(), isMobile ? 500 : 0) onChange,
}, []) }: TextInputProps) => {
const handleInputChange = ( const handleInputChange = (
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement> e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => onChange(e.target.value) ) => onChange(e.target.value)
@ -46,7 +39,7 @@ export const TextInput = ({ block, value, onChange }: TextInputProps) => {
case InputBlockType.TEXT: { case InputBlockType.TEXT: {
return block.options?.isLong ? ( return block.options?.isLong ? (
<LongTextInput <LongTextInput
ref={inputRef as unknown as RefObject<HTMLTextAreaElement>} ref={inputRef}
value={value} value={value}
placeholder={ placeholder={
block.options?.labels?.placeholder ?? 'Type your answer...' block.options?.labels?.placeholder ?? 'Type your answer...'
@ -61,7 +54,6 @@ export const TextInput = ({ block, value, onChange }: TextInputProps) => {
block.options?.labels?.placeholder ?? 'Type your answer...' block.options?.labels?.placeholder ?? 'Type your answer...'
} }
onChange={handleInputChange} onChange={handleInputChange}
autoComplete="new-typebot-answer-value"
/> />
) )
} }
@ -111,14 +103,14 @@ export const TextInput = ({ block, value, onChange }: TextInputProps) => {
case InputBlockType.PHONE: { case InputBlockType.PHONE: {
return ( return (
<PhoneInput <PhoneInput
// eslint-disable-next-line @typescript-eslint/no-explicit-any ref={inputRef}
ref={inputRef as any}
value={value} value={value}
onChange={handlePhoneNumberChange} onChange={handlePhoneNumberChange}
placeholder={ placeholder={
block.options.labels.placeholder ?? 'Your phone number...' block.options.labels.placeholder ?? 'Your phone number...'
} }
defaultCountry={block.options.defaultCountryCode as Country} defaultCountry={block.options.defaultCountryCode as Country}
autoFocus
/> />
) )
} }
@ -136,6 +128,8 @@ const ShortTextInput = React.forwardRef(
type="text" type="text"
required required
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
autoComplete="do-not-autofill"
autoFocus
{...props} {...props}
/> />
) )
@ -157,6 +151,7 @@ const LongTextInput = React.forwardRef(
data-testid="textarea" data-testid="textarea"
required required
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
autoFocus
{...props} {...props}
/> />
) )