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
93 lines
3.5 KiB
PHP
93 lines
3.5 KiB
PHP
{{-- The chrome of M3's text fields, around whichever control is in the slot.
|
|
|
|
Not used at call sites: `<x-input>`, `<x-password>`, `<x-textarea>`, `<x-select>`, `<x-file>`
|
|
and the pickers wrap their control in it, so a form reads as one family. The states — the
|
|
label resting or floating, the notch, focus, disabled, required — are selectors in
|
|
resources/css/components/field.css, which explains the anatomy; the only state this file
|
|
decides is `data-invalid`, because only the server knows that.
|
|
|
|
`variant` is M3's two: `outlined` (a notched outline) and `filled` (a surface-container-highest
|
|
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, 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. --}}
|
|
|
|
@props([
|
|
'id',
|
|
'label' => null,
|
|
'hint' => null,
|
|
'hintClass' => null,
|
|
'messages' => [],
|
|
'icon' => null,
|
|
'prefix' => null,
|
|
'suffix' => null,
|
|
'size' => 'md',
|
|
'variant' => null,
|
|
'floated' => false,
|
|
'mono' => false,
|
|
])
|
|
|
|
@php
|
|
$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="{{ $density }}"
|
|
@if ($messages !== []) data-invalid @endif
|
|
@if ($floated) data-floated @endif
|
|
@if ($mono) data-mono @endif
|
|
>
|
|
<div class="field-box">
|
|
@if ($icon)
|
|
<x-livewire-material::icon :name="$icon" class="field-icon size-(--field-icon)" />
|
|
@endif
|
|
|
|
@if (filled($prefix))
|
|
<span class="field-affix">{{ $prefix }}</span>
|
|
@endif
|
|
|
|
{{ $slot }}
|
|
|
|
@if (filled($suffix))
|
|
<span class="field-affix">{{ $suffix }}</span>
|
|
@endif
|
|
|
|
{{ $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>
|
|
|
|
@if (filled($label))
|
|
<label for="{{ $id }}" class="field-label">{{ $label }}</label>
|
|
@endif
|
|
</div>
|
|
|
|
@if ($messages !== [])
|
|
<div id="{{ $id }}-support" class="field-support" role="alert">
|
|
@foreach ($messages as $message)
|
|
<p>{{ $message }}</p>
|
|
@endforeach
|
|
</div>
|
|
@elseif (filled($hint))
|
|
<p id="{{ $id }}-support" @class(array_filter(['field-support', $hintClass]))>{{ $hint }}</p>
|
|
@endif
|
|
</div>
|