Form and Field
Form turns a submission into one onSubmit call, and Field gives a control
its label, description and error. Press Send with the field empty, then fix
the address and send again:
Not sent yet
import { Paragraph, View } from '@hozo/core'import { Button, Field, Form, Input, Stack, useFormSubmit } from '@hozo/ui'import { useState } from 'react'
// A Button is not a submit button, so it asks the form to submit.function Submit() { const submit = useFormSubmit() return ( <Button tone="accent" onPress={submit}> Send </Button> )}
export function FormDemo() { const [email, setEmail] = useState('') const [tried, setTried] = useState(false) const [sent, setSent] = useState<string>() const wrong = tried && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email) return ( <View className="w-full max-w-md gap-3"> <Form accessibilityLabel="Newsletter" onSubmit={() => { setTried(true) if (/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) setSent(email) }} > <Field label="Email" description="One letter a month, and nothing else." error={wrong ? 'That does not look like an email address.' : undefined} required > {(control) => ( <Input {...control} inputMode="email" value={email} onChangeText={setEmail} placeholder="you@example.com" /> )} </Field> <Stack direction="row" gap="tight"> <Submit /> </Stack> </Form> <Paragraph className="text-sm text-hozo-text-body"> {sent ? `Subscribed ${sent}` : 'Not sent yet'} </Paragraph> </View> )}onSubmitis called with no event. Enter in a field, a real submit button anduseFormSubmit()all arrive there, in one order.- A
Buttonsubmits throughuseFormSubmit(), because a Button is not a<button type="submit">. Call the hook in a component inside the form, as the example’sSubmitdoes. - It does not submit past a control marked
aria-invalid. It focuses that control instead, so a screen reader hears which field is wrong, not only a sighted person.focusInvalidOnSubmit={false}turns that off. accessibilityLabelnames the form.
labellabels the control,descriptionsays what it is for, anderrorsays what is wrong. The control is described by both and markedaria-invalidwhile there is an error.childrenis a function that is givencontrol: the id and the ARIA attributes that connect the control to the label, the description and the error. Spread it ontoInput,TextAreaorNativeSelect.requiredmarks the controlaria-requiredand shows a marker beside the label. It does not add the browser’s ownrequired, so the browser does not show its own message.