{{-- Floating-label text field with a leading icon. The label floats via the `peer-placeholder-shown` technique, which needs a literal single-space placeholder — without it the browser never reports the "empty" state and the label sits over the caret. Errors are rendered from the standard $errors bag and wired with aria-describedby / aria-invalid, so a screen reader announces the message with the field rather than as loose text further down the page. --}} @props([ 'name', 'label', 'type' => 'text', 'icon' => 'envelope', 'autocomplete' => null, 'autofocus' => false, /* | An explicit starting value, for the one case old() cannot cover: the | password-reset form, where the address arrives in the signed link rather | than from a previous submission. Passing it through $attributes instead | would emit a second value attribute, and the hardcoded one below wins. | | Never honoured for password fields — see the input. */ 'value' => null, ]) @php $id = 'auth-'.$name; $hasError = $errors->has($name); @endphp
merge([ 'class' => 'peer h-16 w-full rounded-xl border bg-white/70 px-4 pt-6 ps-12 pb-2 text-[15px] text-slate-900 outline-none transition-all duration-200 placeholder:text-transparent focus:ring-4 dark:bg-slate-800/60 dark:text-white ' .($hasError ? 'border-red-400 focus:border-red-500 focus:ring-red-500/15 dark:border-red-500/60' : 'border-slate-200 hover:border-slate-300 focus:border-brand-500 focus:ring-brand-500/15 dark:border-slate-700 dark:hover:border-slate-600'), ]) }}> {{-- The *floated* position is the base state and "resting over the caret" is the variant. Written the other way round, the resting size is a plain utility and the floated size a variant of equal weight, and which one wins comes down to Tailwind's emission order rather than intent. This way the filled state needs no override at all, and only :focus — which must beat the resting state — carries the important modifier. --}} {{-- Trailing control, e.g. the password reveal button. --}} {{ $slot }}
@error($name)

{{ $message }}

@enderror