Fluxon.Components.Autocomplete (Fluxon v2.0.0)
A modern, accessible autocomplete component with rich search capabilities.
The autocomplete component provides a text input that filters a list of options as the user types, with keyboard navigation and accessibility features. It supports both client-side and server-side search capabilities, making it suitable for both small and large datasets.
Select vs Autocomplete
While both components enable users to choose from a list of options, they offer different interaction patterns that may better suit certain use cases.
Select Component Best suited for browsing through predefined options, especially when users benefit from seeing all choices at once. Supports multiple selection.
Autocomplete Component Optimized for searching through large datasets, with both client and server-side filtering. Features a type-to-search interface with custom empty states and loading indicators.
Key Differences:
Feature | Select | Autocomplete |
---|---|---|
Primary Interaction | Click to browse | Type to search |
Data Size | Small to medium lists | Any size dataset |
Filtering | Client-side only | Client or server-side |
Multiple Selection | Supported | Not supported |
Clearing Selection | Supported | Supported |
Basic Usage
Simple autocomplete with a list of options:
<.autocomplete
name="country"
options={[{"United States", "us"}, {"Canada", "ca"}]}
placeholder="Search countries..."
/>
The autocomplete component follows the same options API as Phoenix.HTML.Form.options_for_select/2
,
supporting multiple formats:
# List of strings
<.autocomplete
name="fruits"
options={["Apple", "Banana", "Cherry", "Date", "Elderberry"]}
placeholder="Search fruits..."
/>
# List of tuples (label, value)
<.autocomplete
name="countries"
options={[
{"United States", "us"},
{"Canada", "ca"},
{"United Kingdom", "uk"},
{"Germany", "de"}
]}
placeholder="Search countries..."
/>
# Keyword list
<.autocomplete
name="languages"
options={[english: "en", spanish: "es", french: "fr", german: "de"]}
placeholder="Search languages..."
/>
# Grouped options
<.autocomplete
name="products"
options={[
{"Fruits", [{"Apple", "apple"}, {"Banana", "banana"}]},
{"Vegetables", [{"Carrot", "carrot"}, {"Broccoli", "broccoli"}]},
{"Grains", [{"Rice", "rice"}, {"Wheat", "wheat"}]}
]}
placeholder="Search products..."
/>
Size Variants
The autocomplete component offers five size variants to accommodate different interface needs:
<.autocomplete name="xs" size="xs" placeholder="Extra small" options={@options} />
<.autocomplete name="sm" size="sm" placeholder="Small" options={@options} />
<.autocomplete name="md" size="md" placeholder="Medium (Default)" options={@options} />
<.autocomplete name="lg" size="lg" placeholder="Large" options={@options} />
<.autocomplete name="xl" size="xl" placeholder="Extra large" options={@options} />
Each size variant adjusts the height, padding, font size, and icon dimensions proportionally:
"xs"
: Extra small (h-7), suitable for compact UIs and dense layouts"sm"
: Small (h-8), good for secondary or supporting inputs"md"
: Default (h-9), recommended for most use cases"lg"
: Large (h-10), suitable for prominent or important inputs"xl"
: Extra large (h-11), ideal for hero sections or primary actions
Labels and Descriptions
Provide context and guidance with comprehensive labeling options:
# Basic label
<.autocomplete
name="language"
label="Programming Language"
placeholder="Select your favorite..."
options={["Elixir", "Phoenix", "LiveView", "Ecto", "OTP"]}
/>
# Label with sublabel
<.autocomplete
name="database"
label="Database"
sublabel="Required"
placeholder="Choose database..."
options={["PostgreSQL", "MySQL", "SQLite", "MongoDB"]}
/>
# Label with description
<.autocomplete
name="framework"
label="Framework"
description="Choose the web framework for your project"
placeholder="Search frameworks..."
options={["Phoenix", "Rails", "Django", "Express", "FastAPI"]}
/>
# Complete example with all text features
<.autocomplete
name="deployment"
label="Deployment Platform"
sublabel="Optional"
description="This will determine your deployment configuration"
help_text="Choose from our supported platforms"
placeholder="Select platform..."
options={["Fly.io", "Railway", "Heroku", "Render", "AWS"]}
/>
Form Integration
The autocomplete component integrates with Phoenix forms in two ways: using the field
attribute for form integration
or using the name
attribute for standalone inputs.
Using with Phoenix Forms (Recommended)
Use the field
attribute to bind the autocomplete to a form field:
<.form :let={f} for={@changeset} phx-change="validate" phx-submit="save">
<.autocomplete
field={f[:user_id]}
label="Assigned To"
options={@users}
/>
</.form>
Using the field
attribute provides:
- Automatic value handling from form data
- Error handling and validation messages
- Form submission with correct field names
- Integration with changesets
- Nested form data handling
Complete example with changeset implementation:
defmodule MyApp.Task do
use Ecto.Schema
import Ecto.Changeset
schema "tasks" do
field :title, :string
belongs_to :assigned_to, MyApp.User
timestamps()
end
def changeset(task, attrs) do
task
|> cast(attrs, [:assigned_to_id, :title])
|> validate_required([:assigned_to_id])
end
end
# In your LiveView
def mount(_params, _session, socket) do
users = MyApp.Accounts.list_active_users() |> Enum.map(&{&1.name, &1.id})
changeset = Task.changeset(%Task{}, %{})
{:ok, assign(socket, users: users, form: to_form(changeset))}
end
def render(assigns) do
~H"""
<.form :let={f} for={@form} phx-change="validate">
<.autocomplete
field={f[:assigned_to_id]}
options={@users}
label="Assigned To"
placeholder="Search users..."
/>
</.form>
"""
end
def handle_event("validate", %{"task" => params}, socket) do
changeset =
%Task{}
|> Task.changeset(params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, form: to_form(changeset))}
end
Using Standalone Autocomplete
For simpler cases or when not using Phoenix forms, use the name
attribute:
<.autocomplete
name="search_user"
options={@users}
value={@user_id}
placeholder="Search users..."
/>
Input States
The autocomplete component supports various input states for different use cases:
Disabled State
Disable the autocomplete to prevent user interaction:
# Disabled empty autocomplete
<.autocomplete
name="disabled_empty"
label="Unavailable Option"
disabled
placeholder="This option is currently disabled"
options={["Option 1", "Option 2", "Option 3"]}
/>
# Disabled with pre-selected value
<.autocomplete
name="disabled_selected"
label="Read-only Selection"
disabled
value="Option 2"
options={["Option 1", "Option 2", "Option 3"]}
/>
Error States
Display validation errors below the autocomplete:
# Single error
<.autocomplete
name="single_error"
label="Required Field"
placeholder="This field is required"
options={["Option 1", "Option 2", "Option 3"]}
errors={["This field is required"]}
/>
# Multiple errors
<.autocomplete
name="multiple_errors"
label="Field with Multiple Issues"
placeholder="Multiple validation errors"
options={["Option 1", "Option 2", "Option 3"]}
errors={["This field is required", "Please select a valid option"]}
/>
Inner Affixes
Use the :inner_prefix
and :inner_suffix
slots to add content inside the autocomplete's border.
This is useful for icons, status indicators, or visual enhancements that should appear within the input field.
# Search icon prefix
<.autocomplete name="user_search" options={@users} placeholder="Search users...">
<:inner_prefix>
<.icon name="hero-magnifying-glass" class="size-4" />
</:inner_prefix>
</.autocomplete>
# Email validation with status
<.autocomplete name="email" options={@emails} placeholder="user@example.com">
<:inner_prefix>
<.icon name="hero-at-symbol" class="size-4" />
</:inner_prefix>
<:inner_suffix>
<.icon name="hero-check-circle" class="size-4 text-green-500" />
</:inner_suffix>
</.autocomplete>
# Location search with emoji
<.autocomplete name="location" options={@locations} placeholder="City name">
<:inner_prefix class="text-foreground-softest">📍</:inner_prefix>
</.autocomplete>
# Both inner affixes combined
<.autocomplete name="comprehensive" options={@options} placeholder="Search...">
<:inner_prefix>
<.icon name="hero-magnifying-glass" class="size-4" />
</:inner_prefix>
<:inner_suffix>
<.icon name="hero-information-circle" class="size-4" />
</:inner_suffix>
</.autocomplete>
Outer Affixes
Use the :outer_prefix
and :outer_suffix
slots to add content outside the autocomplete's border.
This is ideal for buttons, labels, or interactive elements that complement the search functionality.
# Simple text prefix
<.autocomplete name="filtered" options={@options} placeholder="Search...">
<:outer_prefix class="px-3 text-foreground-soft">Filter:</:outer_prefix>
</.autocomplete>
# Action button suffix
<.autocomplete name="with_action" options={@options} placeholder="Search...">
<:outer_suffix>
<.button size="md">Search</.button>
</:outer_suffix>
</.autocomplete>
# User invitation with send button
<.autocomplete name="invite_user" options={@users} placeholder="Search users...">
<:inner_prefix>
<.icon name="hero-user-plus" class="size-4" />
</:inner_prefix>
<:outer_suffix>
<.button variant="solid" color="primary" size="md">
<.icon name="hero-paper-airplane" class="size-4" /> Invite
</.button>
</:outer_suffix>
</.autocomplete>
# All affixes combined
<.autocomplete name="comprehensive" options={@options} placeholder="Search...">
<:outer_prefix class="px-2">Search</:outer_prefix>
<:inner_prefix>
<.icon name="hero-magnifying-glass" class="size-4" />
</:inner_prefix>
<:inner_suffix>
<.icon name="hero-information-circle" class="size-4" />
</:inner_suffix>
<:outer_suffix>
<.button size="md">Go</.button>
</:outer_suffix>
</.autocomplete>
Size Matching with Affixes
When using buttons or other components within affix slots, ensure their
size
attribute matches the autocomplete'ssize
for proper visual alignment. For example, if the autocomplete issize="lg"
, use buttons withsize="lg"
as well.
Search Behavior
The autocomplete component offers flexible search strategies to handle different use cases and data sources.
Client-side Search
Client-side search provides immediate feedback as users type, filtering the provided options directly in the browser. This approach is ideal for small to medium datasets.
Search Modes
Control how options are matched against the search query:
# Contains (default) - matches anywhere in the option
<.autocomplete
name="contains_search"
label="Contains Search"
search_mode="contains"
placeholder="Type any part of the word..."
options={["JavaScript", "TypeScript", "CoffeeScript", "ReScript"]}
/>
# Starts with - matches only at the beginning
<.autocomplete
name="starts_with_search"
label="Starts With Search"
search_mode="starts-with"
placeholder="Type beginning of word..."
options={["JavaScript", "TypeScript", "CoffeeScript", "ReScript"]}
/>
# Exact match - requires exact matching
<.autocomplete
name="exact_search"
label="Exact Match"
search_mode="exact"
placeholder="Type exact match..."
options={["JavaScript", "TypeScript", "CoffeeScript", "ReScript"]}
/>
Search Thresholds
Control when filtering begins based on the number of characters typed:
# No threshold - search immediately
<.autocomplete
name="no_threshold"
label="Immediate Search"
search_threshold={0}
placeholder="Search immediately..."
options={["React", "Vue", "Angular", "Svelte", "Solid"]}
/>
# 2 character threshold
<.autocomplete
name="threshold_2"
label="2 Character Minimum"
search_threshold={2}
placeholder="Type 2+ characters..."
options={["React", "Vue", "Angular", "Svelte", "Solid"]}
/>
# 3 character threshold
<.autocomplete
name="threshold_3"
label="3 Character Minimum"
search_threshold={3}
placeholder="Type 3+ characters..."
options={["React", "Vue", "Angular", "Svelte", "Solid"]}
/>
Server-side Search
For large datasets, dynamic data sources, or when complex search logic is required, the component supports server-side search through LiveView integration:
<.autocomplete
name="movie"
options={@movies}
on_search="search_movies"
search_threshold={2}
placeholder="Type to search movies..."
/>
In your LiveView, handle the search event to fetch and update the options:
def mount(_params, _session, socket) do
{:ok, assign(socket, movies: [])}
end
def handle_event("search_movies", %{"query" => query}, socket) when byte_size(query) >= 2 do
case MyApp.Movies.search(query) do
{:ok, movies} ->
{:noreply, assign(socket, movies: movies)}
{:error, _reason} ->
{:noreply, assign(socket, movies: [])}
end
end
The component automatically manages the search state, including:
- Debouncing requests to prevent excessive server calls
- Displaying a loading indicator during searches
- Maintaining the selected value while searching
- Handling empty states and error conditions
⚠️ Selected Value and Initial Options
When using server-side search with a selected value, ensure that the selected option is included in the initial options list:
def mount(_params, _session, socket) do
featured_users = MyApp.Accounts.featured_users() |> Enum.map(&{&1.name, &1.id})
selected_user = MyApp.Accounts.get_user!(2)
# Good: Include the selected user in initial options
{:ok, assign(socket,
selected_user_id: selected_user.id,
users: [{selected_user.name, selected_user.id} | featured_users]
)}
end
Advanced Features
Open on Focus
By default, the listbox opens when users start typing. Enable open_on_focus
to show options
immediately when the input is focused:
# Normal behavior - opens when typing
<.autocomplete
name="normal"
label="Normal Behavior"
placeholder="Type to see options..."
options={["Option 1", "Option 2", "Option 3"]}
/>
# Opens immediately on focus
<.autocomplete
name="open_on_focus"
label="Open on Focus"
open_on_focus
placeholder="Click to see all options..."
options={["Option 1", "Option 2", "Option 3"]}
/>
Clearable Selection
Add a clear button to allow users to easily reset their selection:
# Not clearable (default)
<.autocomplete
name="not_clearable"
label="Standard Autocomplete"
placeholder="No clear button..."
options={["Option 1", "Option 2", "Option 3"]}
/>
# Clearable - adds × button when value is selected
<.autocomplete
name="clearable"
label="Clearable Autocomplete"
clearable
placeholder="Has clear button when selected..."
options={["Option 1", "Option 2", "Option 3"]}
/>
# Clearable with initial value
<.autocomplete
name="clearable_with_value"
label="Pre-selected with Clear"
clearable
value="Option 2"
options={["Option 1", "Option 2", "Option 3"]}
/>
Custom Option Rendering
The autocomplete component supports rich, custom option rendering through the :option
slot. Each option
receives a tuple {label, value}
that you can use to create sophisticated option displays:
# User selection with avatars
<.autocomplete
name="users"
label="Assign Task To"
placeholder="Search team members..."
options={[
{"John Doe", "john"},
{"Jane Smith", "jane"},
{"Bob Johnson", "bob"},
{"Alice Brown", "alice"}
]}
>
<:option :let={{label, value}}>
<div class="flex items-center gap-3 p-2 rounded-lg in-data-highlighted:bg-zinc-100 in-data-selected:bg-blue-100">
<div class="size-8 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 flex items-center justify-center text-white text-sm font-bold">
{String.first(label)}
</div>
<div>
<div class="font-medium text-sm">{label}</div>
<div class="text-xs text-zinc-500">@{value}</div>
</div>
</div>
</:option>
</.autocomplete>
# Product selection with status and icons
<.autocomplete
name="products"
label="Select Product"
placeholder="Search inventory..."
options={[
{"MacBook Pro 16\"", "mbp16"},
{"MacBook Air 13\"", "mba13"},
{"iMac 24\"", "imac24"},
{"Mac Studio", "studio"}
]}
>
<:option :let={{label, value}}>
<div class="flex items-center justify-between p-2 rounded-lg in-data-highlighted:bg-zinc-100">
<div class="flex items-center gap-3">
<div class="size-10 rounded bg-zinc-100 flex items-center justify-center">
<.icon name="hero-computer-desktop" class="size-5 text-zinc-600" />
</div>
<div>
<div class="font-medium text-sm">{label}</div>
<div class="text-xs text-zinc-500">Model: {value}</div>
</div>
</div>
<div class="text-xs text-green-600 font-medium">In Stock</div>
</div>
</:option>
</.autocomplete>
Header and Footer Content
Add custom content at the top and bottom of the listbox using the :header
and :footer
slots:
# Simple header
<.autocomplete field={f[:category]} options={@categories}>
<:header class="p-3 border-b border-base bg-zinc-50">
<div class="text-sm font-medium text-zinc-700">Popular Categories</div>
</:header>
</.autocomplete>
# Footer with action button
<.autocomplete field={f[:item]} options={@items}>
<:footer class="p-2 border-t border-base">
<.button type="button" size="sm" class="w-full">
<.icon name="hero-plus" class="size-4" /> Create New Item
</.button>
</:footer>
</.autocomplete>
# Both header and footer with filters
<.autocomplete field={f[:product]} options={@products}>
<:header class="p-2 border-b border-base">
<div class="flex gap-2">
<.button size="xs" class="rounded-full" phx-click="filter" phx-value-type="all">All</.button>
<.button size="xs" class="rounded-full" phx-click="filter" phx-value-type="active">Active</.button>
<.button size="xs" class="rounded-full" phx-click="filter" phx-value-type="draft">Draft</.button>
</div>
</:header>
<:footer class="p-2 border-t border-base">
<.button type="button" size="sm" class="w-full" variant="tertiary">
<.icon name="hero-plus" class="size-4" /> Add New Product
</.button>
</:footer>
</.autocomplete>
Empty State Customization
Customize the message displayed when no options match the search query:
# Default empty state
<.autocomplete
name="default_empty"
label="Default Empty Message"
no_results_text="No results found for '%{query}'"
placeholder="Search to see default message..."
options={["Apple", "Banana", "Cherry"]}
/>
# Custom empty state with icon and actions
<.autocomplete
name="custom_empty"
label="Custom Empty State"
placeholder="Search to see custom empty state..."
options={["Apple", "Banana", "Cherry"]}
>
<:empty_state>
<div class="p-4 text-center">
<div class="text-zinc-400">
<.icon name="hero-face-frown" class="size-8 mx-auto mb-2" />
<p class="font-medium">No results found</p>
<p class="text-sm">Try a different search term or check your spelling</p>
</div>
</div>
</:empty_state>
</.autocomplete>
Keyboard Support
The autocomplete component provides comprehensive keyboard navigation:
Key | Element Focus | Description |
---|---|---|
Tab /Shift+Tab | Input | Moves focus to and from the input |
↑ | Input | Opens listbox and highlights last option |
↓ | Input | Opens listbox and highlights first option |
↑ | Option | Moves highlight to previous visible option |
↓ | Option | Moves highlight to next visible option |
Enter | Option | Selects the highlighted option |
Escape | Any | Closes the listbox |
Type characters | Input | Filters options based on input |
Real-world Examples
Task Assignment Interface
<.autocomplete
name="assigned_user"
label="Assign Task To"
description="Select a team member to assign this task"
placeholder="Search by name or email..."
clearable
search_threshold={2}
options={[
{"John Doe (john@example.com)", "john"},
{"Jane Smith (jane@example.com)", "jane"},
{"Bob Johnson (bob@example.com)", "bob"}
]}
>
<:inner_prefix>
<.icon name="hero-magnifying-glass" class="size-4" />
</:inner_prefix>
<:option :let={{label, value}}>
<div class="flex items-center gap-3 p-2">
<div class="size-8 rounded-full bg-blue-500 flex items-center justify-center text-white text-sm font-bold">
{String.first(label)}
</div>
<div class="flex-1">
<div class="font-medium text-sm">{String.split(label, " (") |> hd()}</div>
<div class="text-xs text-zinc-500">
{String.split(label, "(") |> Enum.at(1, "") |> String.replace(")", "")}
</div>
</div>
</div>
</:option>
</.autocomplete>
E-commerce Product Search
<.autocomplete
name="product_search"
label="Product Catalog"
sublabel="Required"
description="Choose a product from our catalog"
help_text="Start typing to search through 1000+ products"
placeholder="Search products..."
clearable
search_threshold={3}
options={[
{"Electronics",
[
{"iPhone 15 Pro", "iphone15pro"},
{"MacBook Air M2", "macbook-air-m2"},
{"AirPods Pro 2", "airpods-pro-2"}
]},
{"Clothing",
[
{"Men's T-Shirt", "mens-tshirt"},
{"Women's Jeans", "womens-jeans"},
{"Winter Jacket", "winter-jacket"}
]}
]}
>
<:inner_prefix>
<.icon name="hero-magnifying-glass" class="size-4" />
</:inner_prefix>
<:outer_suffix>
<.button size="md">Browse</.button>
</:outer_suffix>
<:header class="p-2 border-b border-base bg-zinc-50">
<div class="text-sm text-zinc-600">🔥 Popular products shown first</div>
</:header>
<:footer class="p-2 border-t border-base">
<.button type="button" size="sm" class="w-full" variant="ghost">
Can't find what you're looking for? <span class="text-blue-600">Contact us</span>
</.button>
</:footer>
</.autocomplete>
Server-side User Search
defmodule MyApp.UsersLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, socket |> assign(users: fetch_users()) |> assign(form: to_form(%{}, as: :search))}
end
def render(assigns) do
~H"""
<.form :let={f} for={@form} phx-change="search">
<.autocomplete field={f[:user_id]} options={user_options(@users)} on_search="search_users" clearable>
<:option :let={{label, value}}>
<div class="flex items-center gap-3 p-2 rounded-lg in-data-highlighted:bg-zinc-100 in-data-selected:bg-blue-100">
<img src={user_by_id(value, @users)["image"]} class="size-8 rounded-full" />
<div>
<div class="font-medium text-sm">{label}</div>
<div class="text-xs text-zinc-500">{user_by_id(value, @users)["email"]}</div>
</div>
</div>
</:option>
<:empty_state>
<div class="p-4 text-center text-zinc-500">
<p>No matching users found</p>
<p class="text-sm">Try searching by name or email</p>
</div>
</:empty_state>
</.autocomplete>
</.form>
"""
end
def handle_event("search_users", %{"query" => query}, socket) do
{:noreply, assign(socket, users: fetch_users(query))}
end
def handle_event("search", _params, socket), do: {:noreply, socket}
defp fetch_users(query \\ "") do
case Req.get("https://dummyjson.com/users/search", params: [limit: 10, q: query]) do
{:ok, %{body: %{"users" => users}}} -> users
_ -> []
end
end
defp user_options(users), do: Enum.map(users, &{&1["firstName"] <> " " <> &1["lastName"], &1["id"]})
defp user_by_id(id, users), do: Enum.find(users, &(&1["id"] == id))
end
Summary
Components
Renders an autocomplete component with rich search capabilities and full keyboard navigation support.
Components
Renders an autocomplete component with rich search capabilities and full keyboard navigation support.
This component provides a flexible way to build search interfaces with real-time filtering, server-side search capabilities, and rich option rendering. It includes built-in form integration, error handling, and accessibility features.
Attributes
id
(:any
) - The unique identifier for the autocomplete component. Defaults tonil
.name
(:any
) - The form name for the autocomplete. Required when not using thefield
attribute.field
(Phoenix.HTML.FormField
) - The form field to bind to. When provided, the component automatically handles value tracking, errors, and form submission.class
(:any
) - Additional CSS classes to apply directly to the autocomplete's field wrapper element (label[data-part=field]
ordiv[data-part=field]
). Allows for custom styling or layout adjustments of the core input container.Defaults to
nil
.label
(:string
) - The primary label for the autocomplete. This text is displayed above the input and is used for accessibility purposes.Defaults to
nil
.sublabel
(:string
) - Additional context displayed to the side of the main label. Useful for providing extra information without cluttering the main label.Defaults to
nil
.help_text
(:string
) - Help text to display below the autocomplete. This can provide additional context or instructions for using the input.Defaults to
nil
.description
(:string
) - A longer description to provide more context about the autocomplete. This appears below the label but above the input element.Defaults to
nil
.placeholder
(:string
) - Text to display in the input when empty. This text appears in the search input and helps guide users to start typing.Defaults to
nil
.autofocus
(:boolean
) - Whether the input should have the autofocus attribute. Defaults tofalse
.disabled
(:boolean
) - When true, disables the autocomplete component. Disabled inputs cannot be interacted with and appear visually muted.Defaults to
false
.size
(:string
) - Controls the size of the autocomplete component:"xs"
: Extra small size, suitable for compact UIs"sm"
: Small size, suitable for compact UIs"md"
: Default size, suitable for most use cases"lg"
: Large size, suitable for prominent inputs"xl"
: Extra large size, suitable for hero sections
Defaults to
"md"
.search_threshold
(:integer
) - The minimum number of characters required before showing suggestions. This helps prevent unnecessary searches and improves performance.Defaults to
0
.no_results_text
(:string
) - Text to display when no options match the search query. Use%{query}
as a placeholder for the actual search term. This is only shown when no custom empty state is provided.Defaults to
"No results found for \"%{query}\"."
.on_search
(:string
) - Name of the LiveView event to be triggered when searching. If provided, filtering will be handled server-side. The event receives%{"query" => query}
as parameters.Defaults to
nil
.debounce
(:integer
) - The debounce time in milliseconds for server-side searches. This delays theon_search
event until the user stops typing for the specified duration.Defaults to
200
.search_mode
(:string
) - The mode of the client-side search to use for the autocomplete:"contains"
: Match if option contains the search query (default)"starts-with"
: Match if option starts with the search query"exact"
: Match only if option exactly matches the search query
Defaults to
"contains"
.open_on_focus
(:boolean
) - When true, the listbox opens when the input is focused, even if no search query has been entered yet.Defaults to
false
.value
(:any
) - The current selected value of the autocomplete. When using forms, this is automatically handled by thefield
attribute.errors
(:list
) - List of error messages to display below the autocomplete. These are automatically handled when using thefield
attribute with form validation.Defaults to
[]
.options
(:list
) (required) - A list of options for the autocomplete. Can be provided in multiple formats:- List of strings:
["Option 1", "Option 2"]
- List of tuples:
[{"Label 1", "value1"}, {"Label 2", "value2"}]
- List of keyword pairs:
[key: "value"]
- List of strings:
animation
(:string
) - The animation style for the listbox. This controls how the listbox appears and disappears when opening/closing.Defaults to
"transition duration-150 ease-in-out"
.animation_enter
(:string
) - CSS classes applied to the listbox when it enters (opens). Defaults to"opacity-100 scale-100"
.animation_leave
(:string
) - CSS classes applied to the listbox when it leaves (closes). Defaults to"opacity-0 scale-95"
.clearable
(:boolean
) - When true, displays a clear button to remove the current selection. This allows users to easily reset the input value without having to delete it manually.Defaults to
false
.Global attributes are accepted. Additional attributes to pass to the form element element. Supports all globals plus:
["form"]
.
Slots
inner_prefix
- Content placed inside the input field's border, before the text entry area. Ideal for icons or short textual prefixes. Can be used multiple times.Accepts attributes:class
(:any
) - CSS classes for styling the inner prefix container.
outer_prefix
- Content placed outside and before the input field. Useful for buttons, dropdowns, or other interactive elements associated with the input's start. Can be used multiple times.Accepts attributes:class
(:any
) - CSS classes for styling the outer prefix container.
inner_suffix
- Content placed inside the input field's border, after the text entry area. Suitable for icons, clear buttons, or loading indicators. Can be used multiple times.Accepts attributes:class
(:any
) - CSS classes for styling the inner suffix container.
outer_suffix
- Content placed outside and after the input field. Useful for action buttons or other controls related to the input's end. Can be used multiple times.Accepts attributes:class
(:any
) - CSS classes for styling the outer suffix container.
option
- Optional slot for custom option rendering. When provided, each option can be fully customized with rich content. The slot receives a tuple{label, value}
for each option.Accepts attributes:class
(:any
) - Additional CSS classes to apply to the option container.
empty_state
- Optional slot for custom empty state rendering. When provided, this content is shown instead of the default "no results" message when no options match the search query.Accepts attributes:class
(:any
) - Additional CSS classes to apply to the empty state container.
header
- Optional slot for custom header rendering. When provided, this content is shown in the top of the listbox.Accepts attributes:class
(:any
) - Additional CSS classes to apply to the header container.
footer
- Optional slot for custom footer rendering. When provided, this content is shown in the bottom of the listbox.Accepts attributes:class
(:any
) - Additional CSS classes to apply to the footer container.