Say a field is in error twice, and stop dashing a read-only one

M3 wants two visual indicators per state and names the pair for a text
field: the error colours and a trailing error icon. The field now draws
one, labelled "Error", unless the caller already trails it or the field
is xs. A read-only field loses its dashed outline: M3 keeps "the same
visual style as an editable field", and the native readonly attribute is
what tells a screen reader. The data-readonly hook stays.

Plan step 20, findings IN-18 and IN-19.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-14 06:09:57 +02:00
co-authored by Claude Fable 5.1
parent 42d62ed00c
commit 856b6f476b
4 changed files with 37 additions and 8 deletions
+12 -2
View File
@@ -10,7 +10,9 @@
box with an indicator line); without it, `config('livewire-material.fields.variant')`. A field
with a label is a form field, M3's 56px. A field without one is a control in a toolbar or an
editor row, and is given `size="sm"` (40px, a button's height) or `size="xs"` (32px). The
error replaces the hint rather than stacking under it, as M3 has it.
error replaces the hint rather than stacking under it, as M3 has it, and an `error` icon joins it
at the end of the row so the state has two indicators and not only a colour unless the caller
trails the field with something of its own, or the field is `xs` and has no room.
`class` from the call site lands on the outermost element, never the control, so a margin or
a width is safe here. --}}
@@ -34,12 +36,16 @@
$variant = in_array($variant, ['outlined', 'filled'], true)
? $variant
: (config('livewire-material.fields.variant') === 'filled' ? 'filled' : 'outlined');
$density = in_array($size, ['sm', 'xs'], true) ? $size : 'md';
// M3 pairs the error colours with a trailing error icon so the state has two indicators. It
// gives way to whatever the caller trails the field with, and to `xs`, which has no room.
$errorIcon = $messages !== [] && ! isset($trailing) && $density !== 'xs';
@endphp
<div
{{ $attributes->class(['field']) }}
data-variant="{{ $variant }}"
data-size="{{ in_array($size, ['sm', 'xs'], true) ? $size : 'md' }}"
data-size="{{ $density }}"
@if ($messages !== []) data-invalid @endif
@if ($floated) data-floated @endif
@if ($mono) data-mono @endif
@@ -61,6 +67,10 @@
{{ $trailing ?? '' }}
@if ($errorIcon)
<x-livewire-material::icon name="error" class="field-trailing field-error size-(--field-icon)" :label="__('Error')" />
@endif
<fieldset aria-hidden="true" class="field-outline">
<legend>@if (filled($label))<span>{{ $label }}</span>@endif</legend>
</fieldset>