Say how M3 wants a checkbox group laid out at expanded
M3 § Checkbox, Behaviour asks that from expanded (840px) related checkboxes be gathered into a contained region rather than left as one long column. That is a rule about the page around the control, not about the control, so it is written down rather than built: the component's header and its SKILL.md entry now say it, and the showcase lays a group out in an `expanded:grid-cols-2` card (plan step 24, audit docs/audits/m3-alignment/inputs.md § Missing). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
72a3e22fbc
commit
cc91e99a5d
@@ -565,7 +565,7 @@ M3 text fields. `variant`: `outlined` or `filled`; without it, `config('livewire
|
||||
|
||||
M3 selection controls on native inputs; the whole row is the label.
|
||||
|
||||
- `<x-checkbox label hint right indeterminate />` — `indeterminate` for a "select all" whose items are partly ticked (bind it to a server expression; it follows every render).
|
||||
- `<x-checkbox label hint right indeterminate />` — `indeterminate` for a "select all" whose items are partly ticked (bind it to a server expression; it follows every render). Grouping is yours: from `expanded` (840px) M3 wants a set of related checkboxes gathered into a contained region rather than one long column, so wrap the set in `<div class="grid gap-4 expanded:grid-cols-2">` (or a card or side sheet) under a heading that names what the group asks.
|
||||
- `<x-radio label wire:model :options inline />` — options `['id', 'name', 'hint', 'disabled']` (`option-value`, `option-label`, `option-hint`); `value` checks an option without `wire:model`; `name` names an unbound group. M3 stacks radios and cautions against a row at any width, so reach for `inline` only for two or three short labels; it also wants five options or fewer and one of them chosen when the page loads.
|
||||
- `<x-toggle label hint right icons />` — M3 switch (`role="switch"`); `icons` puts a check and a cross on the handle, `icons="selected"` only the check. Without `label`, pass `aria-label`.
|
||||
|
||||
|
||||
@@ -10,7 +10,13 @@
|
||||
(resources/css/components/selection.css).
|
||||
|
||||
Without a label — a "select all" in a table header, a row's tick — the row is only the 18px box,
|
||||
so the box carries `touch-target` and catches presses over M3's 48px minimum. --}}
|
||||
so the box carries `touch-target` and catches presses over M3's 48px minimum.
|
||||
|
||||
Grouping is the caller's, not this component's: M3 asks that from `expanded` (840px) a set of
|
||||
related checkboxes be gathered into a contained region rather than left as one long column
|
||||
(docs/reference/m3/components-navigation-selection-inputs.md § Checkbox, Behaviour). Lay the
|
||||
group out yourself — `<div class="grid gap-4 expanded:grid-cols-2">` around the checkboxes, or a
|
||||
`<x-card>` or side sheet holding them — and give the group a heading that names what it asks. --}}
|
||||
|
||||
@props([
|
||||
'label' => null,
|
||||
|
||||
@@ -92,6 +92,23 @@
|
||||
</div>
|
||||
</div>
|
||||
BLADE,
|
||||
'A checkbox group at expanded' => <<<'BLADE'
|
||||
{{-- M3: from expanded (840px), gather related checkboxes into a contained region instead of one long column. --}}
|
||||
<x-card variant="outlined" class="w-full max-w-2xl">
|
||||
<fieldset>
|
||||
<legend class="mb-4 type-title-sm text-on-surface">Tell me about</legend>
|
||||
|
||||
<div class="grid gap-4 expanded:grid-cols-2">
|
||||
<x-checkbox label="Downloads" name="notify[]" value="downloads" checked />
|
||||
<x-checkbox label="Comments" name="notify[]" value="comments" />
|
||||
<x-checkbox label="Expiring shares" name="notify[]" value="expiring" checked />
|
||||
<x-checkbox label="Failed uploads" name="notify[]" value="failed" />
|
||||
<x-checkbox label="New team members" name="notify[]" value="members" />
|
||||
<x-checkbox label="Weekly summary" name="notify[]" value="summary" />
|
||||
</div>
|
||||
</fieldset>
|
||||
</x-card>
|
||||
BLADE,
|
||||
'Radio buttons' => <<<'BLADE'
|
||||
<div class="grid w-full gap-6 medium:grid-cols-2">
|
||||
<x-radio label="Who can open the link" name="showcase-audience" value="password" :options="[['id' => 'anyone', 'name' => 'Anyone with the link'], ['id' => 'password', 'name' => 'Anyone with the password', 'hint' => 'Share the password separately'], ['id' => 'team', 'name' => 'My team only', 'disabled' => true]]" />
|
||||
|
||||
@@ -37,6 +37,29 @@ it('gives a selection control without a label a 48px target', function () {
|
||||
->and((string) $this->blade('<x-radio :options="[[\'id\' => \'a\', \'name\' => \'A\']]" />'))->not->toContain('touch-target');
|
||||
});
|
||||
|
||||
it('leaves a checkbox group to the caller and says how M3 wants it laid out', function () {
|
||||
$html = (string) $this->blade(<<<'BLADE'
|
||||
<fieldset>
|
||||
<legend>Tell me about</legend>
|
||||
<div class="grid gap-4 expanded:grid-cols-2">
|
||||
<x-checkbox label="Downloads" name="notify[]" value="downloads" />
|
||||
<x-checkbox label="Comments" name="notify[]" value="comments" />
|
||||
</div>
|
||||
</fieldset>
|
||||
BLADE);
|
||||
|
||||
expect($html)
|
||||
->toContain('class="grid gap-4 expanded:grid-cols-2"')
|
||||
->toContain('Downloads')
|
||||
->toContain('Comments')
|
||||
->and(substr_count($html, 'data-checkbox'))->toBe(2);
|
||||
|
||||
// The rule is guidance, not markup, so the component's header has to carry it.
|
||||
expect(file_get_contents(__DIR__.'/../../../resources/views/components/checkbox.blade.php'))
|
||||
->toContain('expanded')
|
||||
->toContain('contained region');
|
||||
});
|
||||
|
||||
it('puts a checkbox at the end of its row on request', function () {
|
||||
expect((string) $this->blade('<x-checkbox label="Show" right />'))->toContain('flex-row-reverse justify-between');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user