Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 3x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 3x | import InputErrorMessage from './InputErrorMessage'
import InputLabel from './InputLabel'
export interface InputFieldProps {
errorMessage?: string
helpMessage?: React.ReactNode
helpMessageSecondary?: React.ReactNode
id: string
label: string
max?: string
name: string
onChange?: React.ChangeEventHandler<HTMLInputElement>
required?: boolean
textRequired?: string
type?: React.HTMLInputTypeAttribute
value?: string | number | readonly string[]
}
const InputField = ({
errorMessage,
helpMessage,
helpMessageSecondary,
id,
label,
max,
name,
onChange,
required,
textRequired,
type,
value,
}: InputFieldProps) => {
const inputErrorMessageId = `input-${id}-error`
const inputHelpMessageId = `input-${id}-help`
const inputHelpMessageSecondaryId = `input-${id}-help-secondary`
const inputWrapperId = `input-${id}`
const inputLabelId = `input-${id}-label`
const getAriaDescribedby = () => {
const ariaDescribedby: string[] = []
if (errorMessage) ariaDescribedby.push(inputErrorMessageId)
if (helpMessage) ariaDescribedby.push(inputHelpMessageId)
Iif (helpMessageSecondary) ariaDescribedby.push(inputHelpMessageSecondaryId)
return ariaDescribedby.length > 0 ? ariaDescribedby.join(' ') : undefined
}
return (
<div className="mb-4" id={inputWrapperId} data-testid={id}>
<InputLabel
id={inputLabelId}
htmlFor={id}
required={required}
label={label}
textRequired={textRequired}
/>
{errorMessage && (
<InputErrorMessage id={inputErrorMessageId} message={errorMessage} />
)}
{helpMessage && (
<div
className="mb-1.5 max-w-prose text-base text-gray-600"
id={inputHelpMessageId}
>
{helpMessage}
</div>
)}
<input
aria-describedby={getAriaDescribedby()}
aria-invalid={errorMessage ? true : undefined}
aria-labelledby={inputLabelId}
aria-required={required ? true : undefined}
className={`block h-9 rounded border px-3 py-1.5 ${
errorMessage ? 'border-accent-error' : 'border-neutral-400'
} focus:border-sky-500 focus:outline-none focus:ring-sky-500`}
id={id}
max={max}
name={name}
onChange={onChange}
type={type}
value={value ?? ''}
/>
{helpMessageSecondary && (
<div
className="mt-1.5 max-w-prose text-base text-gray-600"
id={inputHelpMessageSecondaryId}
>
{helpMessageSecondary}
</div>
)}
</div>
)
}
InputField.defaultProps = {
type: 'text',
}
export default InputField
|