Say hello to the v3.2.0! Three new components added: Accordion, Calendar and Timeline.

Powerful suite of Blade components for TALL Stack apps.

AutoComplete

Form auto-complete component.

The autocomplete is an input-first single-select component: a regular text input paired with a floating dropdown of suggestions that filters as the user types. Each item supports a value , an optional description shown as a subtitle line, and an optional image rendered as a circular avatar to the left. Free text is allowed by default; an opt-in strict mode constrains wire:model to predefined values only. Items can be supplied locally via :items or fetched on demand with :request .

The component does not support multiple selection. Reach for Select Styled when multiple selection is required.

Provide a list of items via the items attribute. Each item must have a value key, which is both the visible text and the value bound to wire:model . Filtering is case-insensitive and runs fully client-side.

<!-- "items" accepts a plain array or a collection instance -->
 
<x-autocomplete :items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
['value' => 'Belo Horizonte'],
['value' => 'Curitiba'],
['value' => 'Porto Alegre'],
]" />
Start typing to filter the list
<x-autocomplete label="City"
hint="Start typing to filter the list"
placeholder="Choose a city"
:items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
['value' => 'Belo Horizonte'],
]" />
<x-autocomplete label="Assignee" :items="[
['value' => 'Taylor Otwell', 'description' => 'Creator of Laravel'],
['value' => 'Nuno Maduro', 'description' => 'Creator of PestPHP'],
['value' => 'Jess Archer', 'description' => 'Creator of Laravel Prompts'],
]" />
<x-autocomplete label="Assignee" :items="[
[
'value' => 'Taylor Otwell',
'description' => 'Creator of Laravel',
'image' => 'https://unavatar.io/github/taylorotwell',
],
[
'value' => 'Nuno Maduro',
'description' => 'Creator of PestPHP',
'image' => 'https://unavatar.io/github/nunomaduro',
],
[
'value' => 'Jess Archer',
'description' => 'Creator of Laravel Prompts',
'image' => 'https://unavatar.io/github/jessarcher',
],
]" />

An option to dim a row and block its selection.

<x-autocomplete label="Status" :items="[
['value' => 'Pending'],
['value' => 'Approved'],
['value' => 'Rejected', 'disabled' => true],
]" />
<x-autocomplete label="City" clearable :items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
['value' => 'Belo Horizonte'],
]" />
www
.com
<x-autocomplete label="IA"
prefix="www"
suffix=".com"
:items="[
['value' => 'claude'],
['value' => 'chatgpt'],
['value' => 'gemini.google'],
]" />

The lazy attribute defines the minimum number of characters the user must type before the dropdown is allowed to open. Below the threshold the panel stays closed; once the user crosses it, the panel opens normally.

<x-autocomplete label="City" lazy="2" :items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
['value' => 'Belo Horizonte'],
['value' => 'Curitiba'],
['value' => 'Porto Alegre'],
['value' => 'Salvador'],
['value' => 'Recife'],
['value' => 'Fortaleza'],
]" />

By default, wire:model reflects whatever the user types, even values that don't appear in the list. With strict , the binding only updates when a row is picked from the dropdown. If the user blurs or presses Esc with an unmatched query, the input reverts to the last selected value (or empties if nothing was ever picked).

<x-autocomplete label="Status" strict :items="[
['value' => 'Pending'],
['value' => 'Approved'],
['value' => 'Rejected'],
]" />

A global default is available so an entire application can opt every autocomplete into strict mode at once via configuration:

// config/tallstackui.php
 
'autocomplete' => [
Components\Form\Autocomplete\Component::class,
[
/*
|----------------------------------------------------------------------
| Autocomplete Global Settings
|----------------------------------------------------------------------
| strict: when true, all autocomplete components will, by default, only
| accept values that exist in their items list. The wire:model is only
| updated when a row is picked from the dropdown, and the input reverts
| to the last selected value on blur with an unmatched query.
*/
'strict' => false,
],
],

Similar to the select.styled component, the autocomplete can fetch items from a remote endpoint as the user types.

<!-- Using a route as a string -->
<x-autocomplete label="User" request="/api/users" />
 
<!-- Using a Laravel route -->
<x-autocomplete label="User" :request="route('api.users')" />

For finer control, you can pass request as an array containing: the url key; also method which accepts get or post and params , that is are hydrated on every request, so reactive Livewire properties placed there stay up to date.

<x-autocomplete label="User" :request="[
'url' => route('api.users'),
'method' => 'post',
'params' => ['team_id' => 7],
]" />

The endpoint must return items shaped the same way as :items , value , optional description , optional image , optional disabled :

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
 
Route::get('/users', function (Request $request) {
$search = $request->get('search');
 
return User::query()
->when($search, fn ($query) => $query->where('name', 'like', "%{$search}%"))
->limit(10)
->get()
->map(fn (User $user): array => [
'value' => $user->name,
'description' => $user->email,
'image' => $user->avatar,
]);
})->name('api.users');

The items and request attributes are mutually exclusive and cannot be defined at the same time.

Combine request with lazy to avoid firing a request on every keystroke. The dropdown only opens (and the request only goes out) once the query crosses the threshold.

<x-autocomplete label="User" request="/api/users" lazy="2" clearable />
<x-autocomplete label="City" disabled :items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
]" />

You can override the translation strings used inside the component. All available keys are default (input placeholder), empty (no results message), and loading (remote-source spinner caption).

<x-autocomplete label="User"
request="/api/users"
:placeholders="[
'default' => 'Type a user name...',
'empty' => 'No user matches your search.',
'loading' => 'Searching users...',
]" />

An option to rendered inside the dropdown when the filtered list is empty.

Try searching for a non-existent value
<x-autocomplete label="City" :items="[
['value' => 'São Paulo'],
['value' => 'Rio de Janeiro'],
]">
<x-slot:after>
<div class="my-2 flex items-center justify-center px-2">
<x-button xs x-on:click="$tsui.interaction('dialog').success('Done!', `Term: ${search}`).send()">
<span x-html="`Create city <b>${search}</b>`"></span>
</x-button>
</div>
</x-slot:after>
</x-autocomplete>

The component dispatches AlpineJS events for every meaningful interaction. The select event payload exposes the picked row at $event.detail.item , including any extra keys you put on it.

<!-- $event.detail.item: the picked row, including any extra keys you put on it. -->
 
<x-autocomplete label="User" :items="[
['value' => 'Alice', 'description' => 'admin'],
['value' => 'Bob', 'description' => 'editor'],
]"
x-on:select="alert(`Selected: ${$event.detail.item.value}`)"
x-on:clear="alert('Cleared')"
x-on:open="console.log('opened')"
x-on:close="console.log('closed')" />

Code highlighting provided by Torchlight