From eb470d86d682b7362bfe1873f5b2918426c22027 Mon Sep 17 00:00:00 2001 From: Josh Bruce Date: Thu, 15 Oct 2026 13:08:36 -0400 Subject: [PATCH] docs: add 5.0 migration guide Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/README.md b/README.md index 0886f1f..4dba67e 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,94 @@ Output: ``` +## Migrating from 4.x to 5.0 + +This section highlights the changes to check when upgrading from 4.4.0. It +links to the [form control guidance](#form-control-guidance) for details that +apply to the new and existing APIs. + +### Required migration checks: markup and property targets + +Text-entry controls now render an outer `
` unconditionally. In 4.4.0, +`TextInput` and `EmailInput` rendered their label and input as siblings without +that container. Update CSS child/sibling selectors, flex or grid layouts, and +JavaScript traversal that assumed the old structure. + +```html + + + + +
+ +
+``` + +Use each property method for its element: `containerProps()` targets the outer +container, `labelProps()` targets the label (or a Select group's legend), and +`inputProps()` targets the input or select. For example: + +```php +use Eightfold\HtmlBuilder\Forms\TextInput; + +TextInput::create('Email', 'email') + ->containerProps('class field') + ->labelProps('class field-label') + ->inputProps('class form-control'); +``` + +Do not use `inputProps()` or `labelProps()` to replace generated properties +such as `type`, `id`, `name`, `value`, or the label's `for` association. For +example, 4.4.0 allowed `TextInput::create('Email', 'email')->inputProps('type email')` +to change its generated type; in 5.0, use `EmailInput` instead. Use constructor +arguments, `id()`, or the component/mode that matches the control you need. +Setting a custom ID changes the DOM ID and its generated label and warning +associations, but does not change the submitted field name: + +```php +TextInput::create('Email', 'account_email')->id('email-field'); +// The input has id="email-field" and name="account_email". +``` + +### Choose Select modes and names explicitly + +The default remains a single dropdown. `multiple()`, `radio()`, and +`checkbox()` explicitly choose the other modes. The initial selection is +single-valued for dropdowns and radio groups (only the first supplied value is +considered), and every matching value is selected for multiple dropdowns and +checkbox groups. + +Dropdowns, including multiple dropdowns, and radio groups submit the supplied +name unchanged. Include `[]` yourself when a multiple dropdown should submit a +PHP array. Checkbox groups continue to append `[]` unless the supplied name +already ends with it. `checked` and `multiple` passed through `inputProps()` are +ignored; use the selection argument and mode methods instead. See +[Select attributes and selection](#select-attributes-and-selection) for native +attribute targets and examples. + +### Update custom PropertyInterface implementations + +`PropertyInterface` now extends PHP's `Stringable`. Any custom implementation +must add `public function __toString(): string` alongside `prop()` and +`props()`. + +### Additive APIs and deprecated, still-working calls + +`containerProps()` is available for form controls, and `id()` is available on +TextInput, EmailInput, Password, TextArea, and Select. Select also adds +`multiple()` and `inputProps()`. These APIs are additive. + +`wrapperProps()` remains callable as a forwarding alias throughout 5.x. It +continues to set the same container properties, but is deprecated in favor of +`containerProps()` and emits `E_USER_DEPRECATED`. The native `#[Deprecated]` +attribute is supported by PHP 8.4 and later; removal is deferred until at +least 6.0. See [Migrating from wrapperProps](#migrating-from-wrapperprops). + +Escaping remains caller-owned; this upgrade does not introduce automatic +escaping. `TextArea` is a new control, and its caller-supplied, already-escaped +value is rendered as text content. Its leading-newline and newline-normalizing +behavior is described in [Textarea values](#textarea-values). + ## Form control guidance `TextInput`, `EmailInput`, `TextArea`, and all `Select` modes preserve help IDs