Select

A customizable select component with native and custom interfaces.

<.select
  field={f[:country]}
  options={[{"United States", "US"}, {"Canada", "CA"}]}
/>

Variants

Native

Use the browser's native select element with custom styling for better mobile compatibility and performance.

<.select
  native
  field={f[:country]}
  options={[{"United States", "US"}, {"Canada", "CA"}]}
/>

Basic Configuration

Configure the select with labels, sublabels, descriptions, and help text to provide context for the selection field.

Required for shipping

Select your delivery country

Shipping rates and times vary by country
<.select
  field={f[:country]}
  options={@options}
  placeholder="Select your delivery country"
  label="Country of Residence"
  sublabel="Required for shipping"
  description="Select your delivery country"
  help_text="Shipping rates and times vary by country"
/>

Selection Modes

Single Selection

Default mode with placeholder text to guide users in option selection.

<.select
  label="Country"
  field={f[:country]}
  placeholder="Select a country"
  options={[
    {"United States", "US"},
    {"Canada", "CA"}
    # ...
  ]}
/>

Multiple Selection

Enable selection of multiple options with checkbox indicators and array-based form submission.

<.select
  multiple
  field={f[:countries]}
  options={[
    {"United States", "US"},
    {"Canada", "CA"},
    {"Mexico", "MX"}
    # ...
  ]}
/>

Maximum Selection

Limit the number of selectable options in multiple selection mode using the max attribute.

<.select
  multiple
  max={2}
  field={f[:countries]}
  options={[{"United States", "US"}, {"Canada", "CA"}]}
/>

Interaction

Searchable

Add client-side filtering with a search input for quick option discovery in large lists.

<.select
  searchable
  field={f[:country]}
  options={[{"United States", "US"}, {"Canada", "CA"}]}
/>

Clearable

Enable option deselection with a clear button and backspace key support.

<.select
  clearable
  placeholder="Select a country"
  field={f[:country]}
  options={[
    {"United States", "US"},
    {"Canada", "CA"}
    # ...
  ]}
/>

Presentation

List Height

Control the maximum height of the options list with automatic scrolling.

<.select
  class="max-h-72"
  name="select"
  options={
    [
      {"Canada", "CA"},
      {"United States", "US"},
      # ...
    ]
  }
/>

Add custom content like action buttons or filters at the top and bottom of the options list using header and footer slots.

<.select
  name="country"
  label="Country"
  options={
    [
      {"United States", "US"},
      {"Canada", "CA"}
      # ...
    ]
  }
>
  <:header class="p-2 text-sm text-gray-500 pb-0">
    <.button size="xs" class="rounded-full">Americas</.button>
    <.button size="xs" class="rounded-full">Europe</.button>
    <.button size="xs" class="rounded-full">Asia-Pacific</.button>
  </:header>
  <:footer class="p-2 border-t text-center">
    <.button type="button" size="sm" class="w-full">
      <.icon name="hero-plus" class="icon" /> Request New Country
    </.button>
  </:footer>
</.select>

Animation

Customize the opening and closing animations of the options list.

<.select
  field={f[:country]}
  animation_enter="scale-100 opacity-100"
  animation_leave="scale-90 opacity-0"
  options={[
    {"United States", "US"},
    {"Canada", "CA"}
    # ...
  ]}
/>

Option Presentation

Custom Options

Render custom option content with support for rich HTML and state-based styling.

<.select
  field={f[:role]}
  placeholder="Role"
  options={Enum.map(@roles, fn role -> {role.value, role.name} end)}
>
  <:option :let={{value, label}}>
    <div class="cursor-default px-3 py-2 rounded-lg [[data-highlighted]_&]:bg-blue-500 [[data-highlighted]_&]:flx-focus:bg-blue-500">
      <div class="font-medium text-sm/6 [[data-highlighted]_&]:text-white"><%= label %></div>
      <div class="text-zinc-500 text-xs [[data-highlighted]_&]:text-zinc-100">
        <%= Enum.find(@roles, fn r -> r.value == value end).description %>
      </div>
    </div>
  </:option>
</.select>


<.select
  field={f[:country]}
  options={Enum.map(@countries, fn country -> {country.iso, country.name} end)}
>
  <:option :let={{value, label}}>
    <div class="cursor-default [[data-highlighted]_&]:bg-zinc-100 px-2 py-1 rounded flx-selected:bg-blue-500 [[data-highlighted]_&]:flx-selected:bg-blue-500">
      <.icon name={icon_name(value)} class="rounded-sm mr-1 shadow w-4" />
      <span class="flx-selected:text-white"><%= label %></span>
    </div>
  </:option>
</.select>

Grouped Options

Organize options into logical groups with optional group headers.

<.select
  field={f[:country]}
  placeholder="Select a country"
  options={[
    {"North America",
     [
       {"United States", "US"},
       {"Canada", "CA"},
       {"Mexico", "MX"}
     ]},
    {"South America",
     [
       {"Brazil", "BR"},
       {"Argentina", "AR"},
       {"Chile", "CL"}
     ]}
  ]}
>
  <:option :let={{label, value}}>
    <div class="flex items-center gap-x-2 p-2 text-sm [[data-highlighted]_&]:bg-blue-50 rounded-lg">
      {label}
      <.badge class="ml-auto">{get_area(value)}</.badge>
    </div>
  </:option>
</.select>

States

Disabled State

Render the select in a disabled state to prevent user interaction.

<.select
  name="country"
  value="US"
  options={[{"United States", "US"}, {"Canada", "CA"}]}
  disabled
/>

Error State

Display validation errors with appropriate visual feedback.

must be a South American country

<.select
  value="fr"
  name="language"
  options={[{"English", "en"}, {"Spanish", "es"}, {"French", "fr"}]}
  errors={["Language not supported"]}
/>