Files
livewire-material/resources/views/components/textarea.blade.php
T
Andreas Reinhold / reiniandClaude Opus 5 0341f9d4ca Draw the text field's chrome without Tailwind
<x-field> renders data-md-field with its props and parts as data-md-*
attributes (box, control, label, outline, support, counter, trailing
buttons), and field.css moves into material.components on tokens: px
geometry, spacing and state tokens, the 600px breakpoint (plan step 36).
Its icons take a size prop, 24/20/16 by the field's size.

Every control the field wraps now marks itself data-md-field-control,
so the inputs, the pickers, choices, field.js, menu.css's select and
listbox rules and timepicker.css follow the renamed hooks. Browser tests
cover the error icon, the disabled field's hover, the counter and the
width bound from 600px.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:08:22 +02:00

48 lines
2.4 KiB
PHP

{{-- A multi-line field: the text field, grown to its content.
It starts at `rows` lines (3) and grows with what is typed up to `max-rows`, then scrolls;
`:autogrow="false"` keeps it at `rows` and lets it be resized by hand, vertically only, so a
form's column never moves. The label rests on the first line rather than in the middle of the
box. `label`, `hint`, `variant`, `counter` for M3's character counter against `maxlength`, and
`full` to span the pane past the 40rem M3 bounds a field to from `medium`; every other
attribute reaches the `<textarea>`. --}}
@props([
'label' => null,
'hint' => null,
'hintClass' => null,
'variant' => null,
'rows' => 3,
'maxRows' => null,
'autogrow' => true,
'counter' => false,
'full' => false,
])
@php
$model = $attributes->whereStartsWith('wire:model')->first();
$placeholder = filled($attributes->get('placeholder')) ? $attributes->get('placeholder') : ' ';
$id = $attributes->get('id') ?? 'field-'.substr(md5($model.'|'.$label.'|textarea'), 0, 12);
// A plain form's field is named, not bound: its errors are under its name (`files[]` → `files`, `a[b]` → `a.b`).
$errorKey = $model ?? (filled($attributes->get('name')) ? str_replace(['[]', '[', ']'], ['', '.', ''], (string) $attributes->get('name')) : null);
$messages = $errorKey !== null && isset($errors) ? \Illuminate\Support\Arr::flatten($errors->get($errorKey)) : [];
// M3's counter needs a maximum to count against: without `maxlength` there is nothing to show.
$max = $counter ? $attributes->get('maxlength') : null;
@endphp
<x-livewire-material::field :$id :$label :$hint :hint-class="$hintClass" :$messages :$variant :counter="$max" :$full :class="$attributes->get('class')" :data-md-readonly="$attributes->get('readonly') ? '' : null">
<textarea
{{ $attributes->except(['class', 'id', 'placeholder']) }}
id="{{ $id }}"
rows="{{ (int) $rows }}"
placeholder="{{ $placeholder }}"
@if ($autogrow)
data-md-autogrow
style="--field-rows: {{ (int) $rows }};@if ($maxRows) --field-max-rows: {{ (int) $maxRows }};@endif"
@endif
@if ($messages !== []) aria-invalid="true" @endif
@if ($messages !== [] || filled($hint)) aria-describedby="{{ $id }}-support" @endif
data-md-field-control
></textarea>
</x-livewire-material::field>