Skip to content

Add a Forms\TextArea component with label, value, and warning associations #45

Closed

Description

@joshbruce

Summary

Add a dedicated multiline text component alongside Forms\TextInput. The current public src/Forms/ directory has no textarea component, so consumers must compose its label, value, and warning associations themselves.

Proposed API

Illustrative API, matching existing component conventions:

use Eightfold\HtmlBuilder\Forms\TextArea;

TextArea::create('Notes', 'notes', "First line\nSecond line", 'Add more detail.')
    ->inputProps('rows 4', 'required required')
    ->labelProps('class notes-label');

create($label, $name, $value = '', $warningMessage = '') could accept the same label/name and warning types as TextInput. inputProps() targets the textarea; labelProps() targets its label.

Possible implementation

Compose HtmlBuilder elements: a label whose for matches the textarea's id, a textarea with matching name, and optional warning markup carrying {name}-warning. With a warning, set aria-invalid="true" and associate it through aria-describedby, preserving any existing help IDs.

Unlike an input, the value belongs in element text, not a value attribute. Define the encoding contract explicitly: raw multiline text versus caller-encoded content must not be ambiguous, and text must be encoded exactly once. Preserve whitespace rather than trimming or normalizing it. HTML ignores one leading newline immediately after a textarea start tag; the renderer must account for that if it promises round-trip preservation of leading newlines (for example, prepend one parser-consumed newline before encoded content).

Keep session stores, posted-value precedence, application validation, and CSS policy outside this generic component. No JavaScript should be needed.

Acceptance coverage

  • Label/control and warning/control associations; no warning attributes when absent.
  • Empty and populated values; leading, internal, and trailing newlines.
  • Text containing </textarea>, <script>, ampersands, and quotes cannot escape into executable markup; no double encoding under the documented contract.
  • Native rows, required, readonly, and disabled attributes.
  • Existing help references survive addition of a warning.
  • Plain-string and PropertyInterface warning forms follow existing conventions without duplicate warning nodes.

Activity

  1. joshbruce commented on Oct 15, 2026

    @joshbruce
    MemberAuthor

    Contract clarification following maintainer feedback on PR #51: TextArea should follow the existing library-wide contract that implementers are responsible for all sanitization and escaping. The issue asks for an explicit encoding contract but does not acknowledge that automatic component encoding would change that contract and impose escaping flags, character encoding, and invalid-character handling on callers.

    The revised approach is to render the caller-supplied value unchanged (apart from the existing parser-consumed leading newline). Callers escape untrusted textarea text using their chosen options before passing it in. Documentation will explicitly warn that unescaped closing textarea tags can introduce markup. Acceptance tests will verify that caller-escaped closing tags, script-like text, ampersands, quotes, and entity syntax round-trip without additional encoding, and that different caller-selected escaping options remain intact.

    This clarifies the safety acceptance criterion as a caller-escaped usage contract, not a guarantee that the component sanitizes arbitrary raw input.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions