feat(inputs): improve input focus behavior
This commit is contained in:
@ -17,7 +17,6 @@ export const SendButton = ({
|
||||
}: SendButtonProps) => {
|
||||
return (
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isDisabled || isLoading}
|
||||
{...props}
|
||||
className={
|
||||
|
@ -6,10 +6,10 @@ import {
|
||||
TextInputBlock,
|
||||
UrlInputBlock,
|
||||
} from 'models'
|
||||
import React, { FormEvent, useState } from 'react'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { InputSubmitContent } from '../../InputChatBlock'
|
||||
import { SendButton } from '../SendButton'
|
||||
import { TextInput } from './TextInputContent'
|
||||
import { TextInput } from './TextInput'
|
||||
|
||||
type TextFormProps = {
|
||||
block:
|
||||
@ -30,6 +30,7 @@ export const TextForm = ({
|
||||
hasGuestAvatar,
|
||||
}: TextFormProps) => {
|
||||
const [inputValue, setInputValue] = useState(defaultValue ?? '')
|
||||
const inputRef = useRef<HTMLInputElement | null>(null)
|
||||
|
||||
const isLongText = block.type === InputBlockType.TEXT && block.options?.isLong
|
||||
|
||||
@ -42,29 +43,41 @@ export const TextForm = ({
|
||||
setInputValue(inputValue)
|
||||
}
|
||||
|
||||
const handleSubmit = (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (inputValue === '') return
|
||||
onSubmit({ value: inputValue })
|
||||
const checkIfInputIsValid = () =>
|
||||
inputValue !== '' && inputRef.current?.reportValidity()
|
||||
|
||||
const submit = () => {
|
||||
if (checkIfInputIsValid()) onSubmit({ value: inputValue })
|
||||
}
|
||||
|
||||
const submitWhenEnter = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') submit()
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex items-end justify-between rounded-lg pr-2 typebot-input w-full"
|
||||
onSubmit={handleSubmit}
|
||||
<div
|
||||
className={
|
||||
'flex items-end justify-between rounded-lg pr-2 typebot-input w-full'
|
||||
}
|
||||
data-testid="input"
|
||||
autoComplete={block.type === InputBlockType.TEXT ? 'off' : 'on'}
|
||||
style={{
|
||||
marginRight: hasGuestAvatar ? '50px' : '0.5rem',
|
||||
maxWidth: isLongText ? undefined : '350px',
|
||||
}}
|
||||
onKeyDown={submitWhenEnter}
|
||||
>
|
||||
<TextInput block={block} onChange={handleChange} value={inputValue} />
|
||||
<TextInput
|
||||
inputRef={inputRef}
|
||||
block={block}
|
||||
onChange={handleChange}
|
||||
value={inputValue}
|
||||
/>
|
||||
<SendButton
|
||||
label={block.options?.labels?.button ?? 'Send'}
|
||||
isDisabled={inputValue === ''}
|
||||
className="my-2 ml-2"
|
||||
onClick={submit}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -6,17 +6,11 @@ import {
|
||||
UrlInputBlock,
|
||||
PhoneNumberInputBlock,
|
||||
} from 'models'
|
||||
import React, {
|
||||
ChangeEvent,
|
||||
ChangeEventHandler,
|
||||
RefObject,
|
||||
useEffect,
|
||||
useRef,
|
||||
} from 'react'
|
||||
import React, { ChangeEvent, ChangeEventHandler } from 'react'
|
||||
import PhoneInput, { Value, Country } from 'react-phone-number-input'
|
||||
import { isMobile } from 'services/utils'
|
||||
|
||||
type TextInputProps = {
|
||||
inputRef: React.RefObject<any>
|
||||
block:
|
||||
| TextInputBlock
|
||||
| EmailInputBlock
|
||||
@ -27,13 +21,12 @@ type TextInputProps = {
|
||||
onChange: (value: string) => void
|
||||
}
|
||||
|
||||
export const TextInput = ({ block, value, onChange }: TextInputProps) => {
|
||||
const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => inputRef.current?.focus(), isMobile ? 500 : 0)
|
||||
}, [])
|
||||
|
||||
export const TextInput = ({
|
||||
inputRef,
|
||||
block,
|
||||
value,
|
||||
onChange,
|
||||
}: TextInputProps) => {
|
||||
const handleInputChange = (
|
||||
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||
) => onChange(e.target.value)
|
||||
@ -46,7 +39,7 @@ export const TextInput = ({ block, value, onChange }: TextInputProps) => {
|
||||
case InputBlockType.TEXT: {
|
||||
return block.options?.isLong ? (
|
||||
<LongTextInput
|
||||
ref={inputRef as unknown as RefObject<HTMLTextAreaElement>}
|
||||
ref={inputRef}
|
||||
value={value}
|
||||
placeholder={
|
||||
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...'
|
||||
}
|
||||
onChange={handleInputChange}
|
||||
autoComplete="new-typebot-answer-value"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -111,14 +103,14 @@ export const TextInput = ({ block, value, onChange }: TextInputProps) => {
|
||||
case InputBlockType.PHONE: {
|
||||
return (
|
||||
<PhoneInput
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
ref={inputRef as any}
|
||||
ref={inputRef}
|
||||
value={value}
|
||||
onChange={handlePhoneNumberChange}
|
||||
placeholder={
|
||||
block.options.labels.placeholder ?? 'Your phone number...'
|
||||
}
|
||||
defaultCountry={block.options.defaultCountryCode as Country}
|
||||
autoFocus
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -136,6 +128,8 @@ const ShortTextInput = React.forwardRef(
|
||||
type="text"
|
||||
required
|
||||
style={{ fontSize: '16px' }}
|
||||
autoComplete="do-not-autofill"
|
||||
autoFocus
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
@ -157,6 +151,7 @@ const LongTextInput = React.forwardRef(
|
||||
data-testid="textarea"
|
||||
required
|
||||
style={{ fontSize: '16px' }}
|
||||
autoFocus
|
||||
{...props}
|
||||
/>
|
||||
)
|
Reference in New Issue
Block a user