You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Composite fieldset input (e.g. date+time pair) with one shared warning wired to each member control #42
A composite field type: a fieldset with a legend grouping several logically-linked inputs (e.g. a date input + a time input forming one date-time moment), where a single warning message renders once for the group and aria-describedby/aria-invalid are wired onto each member control.
Sketch of the consumer-facing shape:
DateTimeInput::create('Start', 'start') // legend + name prefix
->warningMessage($messageOrElement); // renders once, inside the fieldset
<fieldset><legend>Start</legend><labelfor="start-date">Date</label><inputid="start-date" name="start-date" type="date" aria-invalid="true" aria-describedby="start-warning"><labelfor="start-time">Time</label><inputid="start-time" name="start-time" type="time" aria-invalid="true" aria-describedby="start-warning"><pid="start-warning">The start date and time could not be understood.</p></fieldset>
Why is this feature necessary?
The 4.x form inputs cover single-control fields well, and Select 4.1.1 established the pattern for one-warning-per-group (radio/checkbox). A date+time pair is the same shape — one logical value across two controls — but currently has no library home. Consumers (this came up in a WCAG 2.2 SC 3.3.1 inline-warnings implementation) must hand-assemble the fieldset, the legend, the visually-hidden sub-labels, and the shared-warning wiring, and must take care not to hand the warning to either sub-input (which would render it twice). A library type would make the accessible pattern the default rather than a per-consumer rebuild.
Describe alternatives you've considered
Composing two TextInputs inside a hand-built fieldset (what the consumer does today): works, but the shared-warning semantics — one message, wired to both controls — have to be re-derived by every consumer, and the warning API on the single inputs actively encourages the wrong thing (pass the warning to one sub-input, leaving the other unmarked).
Handing the warning to a wrapping Select-like group type: Select is options-based; a free-form input group is a different contract and probably deserves its own class rather than overloading Select.
Happy to share the consumer implementation (legend, sr-only sub-labels, pair naming by {name}-date/{name}-time suffix) as a starting point if useful.
Activity
joshbruce commentedon Oct 5, 2026
#43