Components
Select
Displays a list of options for the user to pick from, triggered by a button.
<x-ui.select>
<x-ui.select-trigger class="w-[180px]" aria-label="Theme">
<x-ui.select-value placeholder="Theme" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-item value="light">Light</x-ui.select-item>
<x-ui.select-item value="dark">Dark</x-ui.select-item>
<x-ui.select-item value="system">System</x-ui.select-item>
</x-ui.select-content>
</x-ui.select>
Branded
The color prop brands the trigger's focus ring.
<div class="flex max-w-xs flex-col gap-3">
<x-ui.select color="#0891b2" placeholder="Pick a theme" :options="['Light', 'Dark', 'System']" />
<p class="text-muted-foreground text-xs">The <code>color</code> prop brands the trigger's focus ring.</p>
</div>
Disabled
<x-ui.select>
<x-ui.select-trigger class="w-[180px] disabled:cursor-not-allowed disabled:opacity-50" aria-label="Theme" disabled>
<x-ui.select-value placeholder="Theme" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-item value="light">Light</x-ui.select-item>
<x-ui.select-item value="dark">Dark</x-ui.select-item>
<x-ui.select-item value="system">System</x-ui.select-item>
</x-ui.select-content>
</x-ui.select>
Grouped
<x-ui.select>
<x-ui.select-trigger class="w-[180px]" aria-label="Select a fruit">
<x-ui.select-value placeholder="Select a fruit" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-group>
<x-ui.select-label>Fruits</x-ui.select-label>
<x-ui.select-item value="apple">Apple</x-ui.select-item>
<x-ui.select-item value="banana">Banana</x-ui.select-item>
<x-ui.select-item value="blueberry">Blueberry</x-ui.select-item>
<x-ui.select-item value="pineapple">Pineapple</x-ui.select-item>
</x-ui.select-group>
</x-ui.select-content>
</x-ui.select>
Indicators
{{-- The custom listbox marks the selected option with a trailing check by default.
Switch to `radio` or `checkbox` — in the compositional API set `indicator` on
<x-ui.select-content> and it cascades to every item. --}}
<x-ui.select :options="['light' => 'Light', 'dark' => 'Dark', 'system' => 'System']" value="system" indicator="radio" />
Multiple
<x-ui.select
multiple
name="frameworks"
placeholder="Select frameworks..."
class="w-[260px]"
:value="['next', 'remix']"
:options="[
'next' => 'Next.js',
'sveltekit' => 'SvelteKit',
'nuxt' => 'Nuxt.js',
'remix' => 'Remix',
'astro' => 'Astro',
]"
/>
Native
{{-- native: a BlatUI-styled real <select> — submits without JS, name-bound, validation-
friendly. Put <option>s in the slot and mark the selected one with `selected`. --}}
<x-ui.select native name="status" aria-label="Status" class="w-[200px]">
<option value="" disabled>Select status…</option>
<option value="active">Active</option>
<option value="pending" selected>Pending</option>
<option value="declined">Declined</option>
</x-ui.select>
Options Array
{{-- Shorthand: pass an [value => label] array instead of composing items by hand. --}}
<x-ui.select
value="banana"
:options="['apple' => 'Apple', 'banana' => 'Banana', 'cherry' => 'Cherry', 'grape' => 'Grape']"
placeholder="Pick a fruit"
class="w-[200px]"
/>
Scrollable
<x-ui.select>
<x-ui.select-trigger class="w-[220px]" aria-label="Select a timezone">
<x-ui.select-value placeholder="Select a timezone" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-group>
<x-ui.select-label>North America</x-ui.select-label>
<x-ui.select-item value="est">Eastern Standard Time (EST)</x-ui.select-item>
<x-ui.select-item value="cst">Central Standard Time (CST)</x-ui.select-item>
<x-ui.select-item value="mst">Mountain Standard Time (MST)</x-ui.select-item>
<x-ui.select-item value="pst">Pacific Standard Time (PST)</x-ui.select-item>
</x-ui.select-group>
<x-ui.select-group>
<x-ui.select-label>Europe & Africa</x-ui.select-label>
<x-ui.select-item value="gmt">Greenwich Mean Time (GMT)</x-ui.select-item>
<x-ui.select-item value="cet">Central European Time (CET)</x-ui.select-item>
<x-ui.select-item value="eet">Eastern European Time (EET)</x-ui.select-item>
<x-ui.select-item value="cat">Central Africa Time (CAT)</x-ui.select-item>
</x-ui.select-group>
<x-ui.select-group>
<x-ui.select-label>Asia</x-ui.select-label>
<x-ui.select-item value="ist">India Standard Time (IST)</x-ui.select-item>
<x-ui.select-item value="jst">Japan Standard Time (JST)</x-ui.select-item>
<x-ui.select-item value="gst">Gulf Standard Time (GST)</x-ui.select-item>
</x-ui.select-group>
</x-ui.select-content>
</x-ui.select>
Sizes
{{-- Trigger sizes via the `size` prop. --}}
<div class="flex flex-wrap items-center gap-3">
@foreach (['sm' => 'Small', 'default' => 'Default', 'lg' => 'Large'] as $size => $label)
<x-ui.select>
<x-ui.select-trigger size="{{ $size }}" class="w-[150px]" aria-label="{{ $label }} size">
<x-ui.select-value placeholder="{{ $label }}" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-item value="apple">Apple</x-ui.select-item>
<x-ui.select-item value="banana">Banana</x-ui.select-item>
<x-ui.select-item value="cherry">Cherry</x-ui.select-item>
</x-ui.select-content>
</x-ui.select>
@endforeach
</div>
Utility Class
{{-- Raw <select> styled by .blat-select — native submit, name-bound, and safe to nest inside
slots. Prefer this over the x-ui.select native component when the control is re-wrapped by
another anonymous component's slot. --}}
<select class="blat-select w-full max-w-sm" name="status" aria-label="Status">
<option value="" disabled selected>Select status…</option>
<option>Active</option>
<option>Pending</option>
<option>Declined</option>
</select>
With Icons
<x-ui.select>
<x-ui.select-trigger class="w-[180px]" aria-label="Status">
<x-ui.select-value placeholder="Status" />
</x-ui.select-trigger>
<x-ui.select-content>
<x-ui.select-item value="online"><x-lucide-circle-check aria-hidden="true" /> Online</x-ui.select-item>
<x-ui.select-item value="away"><x-lucide-clock aria-hidden="true" /> Away</x-ui.select-item>
<x-ui.select-item value="busy"><x-lucide-minus-circle aria-hidden="true" /> Busy</x-ui.select-item>
<x-ui.select-item value="offline"><x-lucide-circle aria-hidden="true" /> Offline</x-ui.select-item>
</x-ui.select-content>
</x-ui.select>
Using with Livewire
wire:model
The examples above are the frontend (Blade + Alpine) usage. Inside a Livewire component, bind
wire:model for two-way
state — same component, no wrappers.
Full Livewire guide →
use Livewire\Component;
class Demo extends Component
{
public string $plan = 'pro';
public function render()
{
return view('livewire.demo');
}
}
<x-ui.select wire:model="plan" :options="['free' => 'Free', 'pro' => 'Pro']" />
API Reference
Props, slots and exposed methods for
<x-ui.select>.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
options |
[value => label]
|
— | Shorthand that auto-composes the trigger, content and items (or native <option>s). Associative keys are values; a plain list uses the value as its own label. Omit it to build the listbox with the compositional slot API instead. |
value |
string|array
|
''
|
The initially selected value. Pass an array of values when multiple is true. |
name |
string
|
— | Form field name. A hidden input mirrors the selection so it submits with a form (as name[] when multiple). |
placeholder |
string
|
''
|
Trigger text shown when nothing is selected. Pass a translated string; empty by default so no English leaks. |
multiple |
bool
|
false
|
Allow picking many values. Selected items render as removable chips in the trigger and the list stays open after each pick. |
native |
bool
|
false
|
Render a styled native <select> (submits without JS) instead of the rich JS listbox. Put <option>s in the slot when not using options. |
size |
string
|
'default'
|
Trigger height. Applies to the native variant.
sm
default
lg
|
color |
string
|
— | A CSS color that brands the trigger's focus ring and selected accent for this instance only. |
indicator |
string
|
'check'
|
How a selected option is marked in the custom listbox (ignored when native): a trailing check, a checkbox box, or a radio dot. In the compositional API, set it on <x-ui.select-content> instead — it cascades to the items.
check
checkbox
radio
|
Slots
| Slot | Description |
|---|---|
default |
The compositional listbox when options is omitted: <x-ui.select-trigger> (with <x-ui.select-value>) followed by <x-ui.select-content> wrapping <x-ui.select-item> entries (optionally grouped with select-group/select-label/select-separator). For the native variant, place plain <option> elements here. |
Methods
Available on the component's Alpine scope — call them from markup in the slot
(e.g. @click="…").
| Method | Description |
|---|---|
openList() |
Opens the listbox and moves focus to the selected (or first) option. |
toggleList() |
Opens the listbox if closed, otherwise closes it. |
close() |
Closes the listbox and returns focus to the trigger. |
selectOption(value, label) |
Selects the given value (toggles it when multiple). Single select also closes the list. |