Draw the checkbox and the selection controls' row without Tailwind

<x-checkbox> renders data-md-checkbox, its box, tick and dash, and its
row, text and errors as data-md-* attributes; the 18px tick takes a size
prop and a label-less box md-touch-target (plan step 36). selection.css
moves into material.components as the row, text and state layer the
three controls share, and each control's drawing goes to its own file:
checkbox.css, radio.css, toggle.css, on the state tokens. The radio and
the switch take the renamed shared hooks now and lose their layout
classes in their own commits. field.js follows data-md-indeterminate.

Renaming the switch's data-handle also stops selection.css matching the
slider's handles, which it drew 24px above the track.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 14:34:00 +02:00
co-authored by Claude Opus 5
parent 3083fe28b2
commit f86afc0542
12 changed files with 510 additions and 365 deletions
+7 -7
View File
@@ -5,7 +5,7 @@
its name — a switch without `label` needs an `aria-label`. `right` puts it at the end of the
row, where a setting's switch usually is. `icons` draws a check on the handle when on and a
cross when off; `icons="selected"` only the check. Every other attribute reaches the `<input>`
(resources/css/components/selection.css).
(resources/css/components/toggle.css).
Without a label the row is only the 52×32 track, so the track carries `touch-target` and catches
presses over M3's 48px minimum. --}}
@@ -24,23 +24,23 @@
@endphp
<div {{ $attributes->only(['class', 'wire:key'])->class(['min-w-0']) }}>
<label for="{{ $id }}" data-selection @class([
<label for="{{ $id }}" data-md-selection-row @class([
'flex gap-4',
'items-start' => filled($hint),
'items-center' => blank($hint),
'flex-row-reverse justify-between' => $right,
])>
<span data-switch @if ($icons) data-icons="{{ $icons }}" @endif @class(['touch-target' => blank($label) && blank($hint)])>
<span data-md-switch @if ($icons) data-md-icons="{{ $icons }}" @endif @class(['touch-target' => blank($label) && blank($hint)])>
<input
{{ $attributes->except(['class', 'id', 'wire:key']) }}
id="{{ $id }}"
type="checkbox"
role="switch"
/>
<span data-handle>
<span data-md-switch-handle>
@if ($icons)
<x-livewire-material::icon name="check" class="size-4" optical="20" data-on />
<x-livewire-material::icon name="close" class="size-4" optical="20" data-off />
<x-livewire-material::icon name="check" class="size-4" optical="20" data-md-switch-on />
<x-livewire-material::icon name="close" class="size-4" optical="20" data-md-switch-off />
@endif
</span>
</span>
@@ -48,7 +48,7 @@
@if (filled($label) || filled($hint))
<span class="min-w-0">
@if (filled($label))
<span class="block type-body-lg text-on-surface" data-selection-label>{{ $label }}</span>
<span class="block type-body-lg text-on-surface" data-md-selection-label>{{ $label }}</span>
@endif
@if (filled($hint))
<span class="mt-0.5 block type-body-sm text-on-surface-variant">{{ $hint }}</span>