Take full on the searchable choice and the pickers, as on every field

`full` takes the 40rem bound off `[data-md-field]` from `medium`, and
`<x-input>`, `<x-password>`, `<x-textarea>`, `<x-select>` and `<x-file>`
pass it to the field they draw. `<x-choices searchable>`,
`<x-datepicker>` and `<x-timepicker>` draw the same field but did not
declare the prop, and their roots only forward `class` and `style`, so
`full` reached no element and the field stopped at 40rem: ReStride's
time zone choice stood narrower than the rows filling its card.

The three now declare `full` and pass it to their field (the date
picker's own field, not the dialog's entry fields). `<x-choices>`' chips
are not a field and have no bound, so they take `full` and render
nothing for it, and a call site can switch `searchable` on and off
without it. The docblocks and the skill list every component that takes
it.

The browser test that bounds a field at 600px now measures a bounded
and a `full` searchable choice, date picker and time picker too; it
fails without the change in Chrome, Firefox and Safari. A feature test
renders `full` on every field-shaped component and none on the chips.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-17 07:04:12 +02:00
co-authored by Claude Opus 5
parent 6d4487feb3
commit 7aa6dc7d33
7 changed files with 60 additions and 14 deletions
+22
View File
@@ -201,6 +201,28 @@ it('bounds a field\'s width from medium unless it is told to fill its pane', fun
expect((string) $this->blade('<x-input label="Share name" full />'))->toContain('data-md-full')
->and((string) $this->blade('<x-textarea label="Message" full />'))->toContain('data-md-full')
->and((string) $this->blade('<x-input label="Share name" />'))->not->toContain('data-md-full');
// Every field-shaped component takes it: the searchable choice and the pickers draw a field too.
$zones = "[['id' => 'Europe/Zurich', 'name' => 'Zurich']]";
foreach ([
'<x-password label="Password" full />',
'<x-select label="Expires" full />',
'<x-file label="Photos" full />',
"<x-choices label=\"Time zone\" searchable full :options=\"{$zones}\" />",
'<x-datepicker label="Starts" full />',
'<x-datepicker label="Trip" range full />',
'<x-timepicker label="At" full />',
] as $blade) {
expect(substr_count((string) $this->blade($blade), 'data-md-full'))->toBe(1, $blade);
}
expect((string) $this->blade("<x-choices label=\"Time zone\" searchable :options=\"{$zones}\" />"))->not->toContain('data-md-full')
->and((string) $this->blade('<x-datepicker label="Starts" />'))->not->toContain('data-md-full')
->and((string) $this->blade('<x-timepicker label="At" />'))->not->toContain('data-md-full')
// Chips are no field and have no bound to take off: `full` is taken, and reaches no element.
->and((string) $this->blade("<x-choices label=\"Days\" full :options=\"{$zones}\" />"))->not->toMatch('/\\bfull\\b|data-md-full/')
->and((string) $this->blade("<x-choices label=\"Days\" single full :options=\"{$zones}\" />"))->not->toMatch('/\\bfull\\b|data-md-full/');
});
it('lays out a form with its actions under an optional divider', function () {