Skip to content

Input

Input is the TextInput primitive with a look. Field gives it a label, a description and an error. Type something that is not an email address:

We use it for the receipt and nothing else.
InputDemo.tsx
import { Field, Input } from '@hozo/ui'
import { useState } from 'react'
export function InputDemo() {
const [email, setEmail] = useState('')
const wrong = email !== '' && !/^\S+@\S+\.\S+$/.test(email)
return (
<Field
label="Email"
description="We use it for the receipt and nothing else."
error={wrong ? 'That does not look like an email address.' : undefined}
required
>
{(control) => <Input {...control} inputMode="email" value={email} onChangeText={setEmail} />}
</Field>
)
}

Field is where the accessibility work is. Four elements have to agree on their ids: the <label for>, an aria-describedby naming both the description and the error, an aria-invalid that matches whether there is an error, and an aria-required that the asterisk alone cannot carry. Field hands all of them to its child through control, so spreading it onto the Input is the whole of the wiring.

  • The error look comes from aria-invalid, not from a prop. The border turns red because Field marked the control invalid, so how it looks and what a screen reader announces cannot disagree.
  • multiline makes it a textarea with a matching height. For a field that grows as it is typed into, use TextArea.
  • value, onChangeText, inputMode and the rest are the primitive’s. Input keeps no state of its own.