Functional Weave
Code in Python

react.form.textarea@1.0.1

README.md

3,575 bytes · view raw

# react.form.textarea

A multi-line text box with its label, an optional hint and error message, and,
when you give it a limit, GOV.UK's character count: a message after the box
saying "You have 12 characters remaining" or "You have 3 words too many" as the
person types. It is the GOV.UK Design System textarea and character count as
one React component.

```tsx
"use client";
import { Textarea } from "#fune/react.form.textarea@^1";

<Textarea id="more-detail" label="Can you provide more detail?"
  hint="Do not include personal or financial information, like your National Insurance number or credit card details."
  maxLength={500} threshold={75} error={errors.moreDetail}
  value={detail} onChange={setDetail} />
```

- **rows** is 5 unless you say otherwise; make it fit the answer you expect.
- **maxLength** counts characters (Unicode code points, so an emoji is one)
  and **maxWords** counts words; give one, not both. The count and its
  wording come from `form.character-count`, which your server can call with
  the same limit so the two never disagree.
- **threshold** (a percentage) hides the message until the text reaches that
  share of the limit, for a limit most people will never get near. The
  message element stays in the page with `hidden`, so it still describes the
  box and the live region is already there when it appears.
- The message sits **after** the textarea, is in the box's
  `aria-describedby` (after the hint and the error) and is an
  `aria-live="polite"` region, so a screen reader hears the count after a
  pause in typing rather than on every key.
- Over the limit, the box gets `fune-textarea--error` and the message
  `fune-character-count__message--over`, but not `aria-invalid`: that is for
  the error message your validation shows after submitting. The box is never
  cut off at the limit (no `maxlength` attribute), as GOV.UK advises, so text
  can be pasted and edited down; validate the limit on the server.
- **value** with **onChange** is controlled; **defaultValue** alone is
  uncontrolled and still counted live. `onChange` is called with the text,
  not the event; **onBlur** is called with nothing when the box loses
  focus, to mark the field touched (`form.state`'s blur). **id** is the textarea's id and, unless **name** says
  otherwise, its submitted name; left out, it is React's `useId()`.

It is a client component (it keeps the text for the count), so its file
starts with `"use client"`.

Errors: `a textarea counts characters or words, not both`, `a threshold needs
a limit`, and those of `form.character-count` (`limit must be a whole number
of at least 1`) and `react.form.form-field` (an id with a space).

Classes: those of `react.form.form-field`, plus `fune-textarea` (and
`fune-textarea--error`), `fune-character-count` on the wrapper when counting,
`fune-character-count__message` (and `fune-character-count__message--over`).

Sources: GOV.UK Design System, "Textarea"
https://design-system.service.gov.uk/components/textarea/ and "Character
count" https://design-system.service.gov.uk/components/character-count/;
govuk-frontend `character-count.mjs` for the wording and threshold
https://github.com/alphagov/govuk-frontend/tree/main/packages/govuk-frontend/src/govuk/components/character-count.

## Notices

Portions derived from GOV.UK Frontend (https://github.com/alphagov/govuk-frontend), Copyright (c) 2017 Crown Copyright (Government Digital Service), under the MIT License; the full notice is in NOTICE.

1.0.1 adds its attribution notices (NOTICE). The code and the tests are unchanged.