tests / feature (8.4) (push) Successful in 1m5s
tests / feature (8.5) (push) Successful in 1m4s
tests / lint (push) Successful in 59s
tests / browser (chrome, chromium) (push) Successful in 2m54s
tests / browser (firefox, firefox) (push) Successful in 3m3s
tests / browser (safari, webkit) (push) Successful in 4m13s
Outlined and filled text fields (input, password, auto-growing textarea, native select with the customizable select menu, file), checkbox with an indeterminate state, radio buttons, the M3 switch and form, ported from ReStride and extended. The first half of Phase 6. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
58 lines
2.4 KiB
PHP
58 lines
2.4 KiB
PHP
{{-- A select: the native `<select>`, drawn as M3's exposed dropdown menu.
|
|
|
|
Native on purpose: the keyboard, type-to-find, the screen reader and the form value are the
|
|
browser's, and `wire:model` binds to it as to any select. Where the browser has the
|
|
customizable select (`appearance: base-select`) its open list is M3's menu, under the field
|
|
and as wide (resources/css/components/menu.css); elsewhere the native list stands in. So the
|
|
options stay plain text: the native list could show nothing more. A select always shows a
|
|
value, so its label always floats.
|
|
|
|
`options` as a list of `['id' => …, 'name' => …]` (`'disabled' => true` greys one out),
|
|
`option-value` and `option-label` to read other keys, and a `placeholder` that becomes the
|
|
first option, valued `placeholder-value` (empty by default). Or pass `<option>`s in the slot.
|
|
`label`, `hint`, `icon`, `variant`, `size`. --}}
|
|
|
|
@props([
|
|
'label' => null,
|
|
'hint' => null,
|
|
'hintClass' => null,
|
|
'icon' => null,
|
|
'options' => [],
|
|
'optionValue' => 'id',
|
|
'optionLabel' => 'name',
|
|
'placeholder' => null,
|
|
'placeholderValue' => null,
|
|
'size' => 'md',
|
|
'variant' => null,
|
|
])
|
|
|
|
@php
|
|
$model = $attributes->whereStartsWith('wire:model')->first();
|
|
$id = $attributes->get('id') ?? 'field-'.substr(md5($model.'|'.$label.'|select'), 0, 12);
|
|
$messages = $model !== null && isset($errors) ? \Illuminate\Support\Arr::flatten($errors->get($model)) : [];
|
|
@endphp
|
|
|
|
<x-field :$id :$label :$hint :hint-class="$hintClass" :$messages :$icon :$size :$variant floated :class="$attributes->get('class')">
|
|
<select
|
|
{{ $attributes->except(['class', 'id']) }}
|
|
id="{{ $id }}"
|
|
@if ($messages !== []) aria-invalid="true" @endif
|
|
@if ($messages !== [] || filled($hint)) aria-describedby="{{ $id }}-support" @endif
|
|
class="field-control"
|
|
>
|
|
@if (filled($placeholder))
|
|
<option value="{{ $placeholderValue }}">{{ $placeholder }}</option>
|
|
@endif
|
|
|
|
@foreach ($options as $option)
|
|
<option value="{{ data_get($option, $optionValue) }}" @disabled(data_get($option, 'disabled'))>{{ data_get($option, $optionLabel) }}</option>
|
|
@endforeach
|
|
|
|
{{ $slot }}
|
|
</select>
|
|
|
|
<x-slot:trailing>
|
|
<x-icon name="arrow_drop_down" class="field-trailing field-arrow size-(--field-icon)" />
|
|
</x-slot:trailing>
|
|
</x-field>
|