Skip to main content

Forms

Select code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/select.blade.php

@props([
    'size' => 'base',
    'invalid' => false,
    'disabled' => false,
    'options' => [],
    'placeholder' => null,
    'selected' => null,
])

@php
    /*
    | Native select with a custom chevron. Pass `options` as [value => label] or
    | use the slot to render <option> tags directly.
    |
    | Usage:
    |   <x-ui.select :options="['us' => 'United States', 'gb' => 'United Kingdom']" placeholder="Choose..." />
    */
    $sizes = [
        'sm' => 'text-sm py-1.5',
        'base' => 'text-sm py-2.5',
        'lg' => 'text-base py-3',
    ];

    $ring = $invalid
        ? 'border-red-400 dark:border-red-500 focus:border-red-500 focus:ring-red-500'
        : 'border-gray-300 dark:border-gray-700 focus:border-brand-500 focus:ring-brand-500';

    $classes = implode(' ', [
        'block w-full appearance-none rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 shadow-sm ps-3.5 pe-10 transition focus:ring-1 disabled:opacity-50 disabled:cursor-not-allowed',
        $sizes[$size] ?? $sizes['base'],
        $ring,
    ]);

    $providedId = $attributes->get('id');
    $providedAriaLabel = $attributes->get('aria-label');
    $providedAriaLabelledBy = $attributes->get('aria-labelledby');
    $providedName = $attributes->get('name');
    $normalizedName = $providedName
        ? trim((string) preg_replace('/[^A-Za-z0-9\-_:.]+/', '-', str_replace(['[', ']'], '', (string) $providedName)), '-')
        : null;
    $selectId = $providedId ?: $normalizedName;
    $fallbackLabel = null;

    if (! $providedAriaLabel && ! $providedAriaLabelledBy && ! $providedId) {
        $fallbackLabel = $placeholder
            ? rtrim((string) $placeholder, '. ')
            : ($providedName ? Str::headline(str_replace(['-', '_'], ' ', $normalizedName ?? (string) $providedName)) : null);
    }
@endphp

<div class="relative">
    <select
        @disabled($disabled)
        @if ($selectId) id="{{ $selectId }}" @endif
        @if ($fallbackLabel) aria-label="{{ $fallbackLabel }}" @endif
        @if ($invalid) aria-invalid="true" @endif
        {{ $attributes->except(['id', 'aria-label'])->merge(['class' => $classes]) }}
    >
        @if ($placeholder)
            <option value="" disabled @selected($selected === null)>{{ $placeholder }}</option>
        @endif

        @foreach ($options as $value => $label)
            <option value="{{ $value }}" @selected((string) $selected === (string) $value)>{{ $label }}</option>
        @endforeach

        {{ $slot }}
    </select>

    <span class="pointer-events-none absolute inset-y-0 end-0 flex items-center pe-3 text-gray-400 dark:text-gray-500">
        <x-ui.icon name="caret-down" weight="bold" size="sm" />
    </span>
</div>