PhiaUi.Components.Select (phia_ui v0.1.17)

Copy Markdown View Source

Native HTML select form component for Phoenix LiveView.

phia_select/1 wraps the browser's native <select> element with PhiaUI styling, a Lucide chevron-down icon overlay, and full Phoenix.HTML.FormField integration including changeset error display.

When to use

Use phia_select/1 for dropdown selection when:

  • The option count is moderate (2–20 options work best with a native dropdown)
  • You want zero JavaScript and full browser accessibility for free
  • A simple, familiar dropdown interaction is appropriate

For searchable or async-loaded options, consider phia_combobox/1 instead.

Basic usage

<.form for={@form} phx-submit="save" phx-change="validate">
  <.phia_select
    field={@form[:country]}
    options={[{"United States", "us"}, {"Canada", "ca"}, {"United Kingdom", "gb"}]}
    label="Country"
    prompt="Select your country"
  />
  <.button type="submit">Save</.button>
</.form>

Options format

The :options attribute accepts any format supported by Phoenix.HTML.Form.options_for_select/2:

<%!-- Tuple list {label, value}  most common --%>
options={[{"Free", "free"}, {"Pro", "pro"}, {"Enterprise", "enterprise"}]}

<%!-- Plain strings  value equals label --%>
options={["Small", "Medium", "Large"]}

<%!-- Keyword list --%>
options={[Free: "free", Pro: "pro"]}

<%!-- Mixed integers --%>
options={[{"1 month", 1}, {"6 months", 6}, {"1 year", 12}]}

Pre-selecting a value

The currently selected value is read from field.value automatically. When a changeset is loaded with existing data, the correct option will be pre-selected:

# In your LiveView mount/2:
changeset = Settings.change_preferences(user.preferences)
assign(socket, form: to_form(changeset))

Prompt (placeholder option)

Use :prompt to render an unselectable leading option:

<.phia_select
  field={@form[:role]}
  options={[{"Admin", "admin"}, {"Member", "member"}, {"Viewer", "viewer"}]}
  label="Role"
  prompt="Choose a role..."
/>

Dynamic options from the database

<.phia_select
  field={@form[:category_id]}
  options={Enum.map(@categories, &{&1.name, &1.id})}
  label="Category"
  prompt="Select a category"
/>

No JavaScript

The component is CSS-only. A chevron-down icon is positioned absolutely inside a pointer-events-none overlay so it does not interfere with the native <select> click target. The browser handles all keyboard navigation and accessibility natively.

Accessibility

The <select> is associated with its <label> via for/id from the field struct. Changeset errors appear below the element in destructive colour. Focus states use PhiaUI's standard ring tokens.

Summary

Functions

Renders a native <select> element integrated with Phoenix.HTML.FormField.

Functions

phia_select(assigns)

Renders a native <select> element integrated with Phoenix.HTML.FormField.

No JavaScript is required — the browser's native dropdown handles all interaction. A chevron-down icon is positioned absolutely on the right with pointer-events-none so it overlays the select without interfering with clicks. The :options list is rendered via Phoenix.HTML.Form.options_for_select/2, which marks the correct <option> as selected based on field.value.

An optional :prompt renders a leading <option value=""> placeholder. Changeset errors from field.errors are displayed below the element by the form_field/1 wrapper.

Examples

<%!-- User role assignment --%>
<.phia_select
  field={@form[:role]}
  options={[{"Admin", "admin"}, {"Member", "member"}, {"Viewer", "viewer"}]}
  label="Role"
  prompt="Select a role..."
/>

<%!-- Subscription plan selector --%>
<.phia_select
  field={@form[:plan]}
  options={[{"Free", "free"}, {"Pro", "pro"}, {"Enterprise", "enterprise"}]}
  label="Plan"
/>

<%!-- Dynamic options from assigns --%>
<.phia_select
  field={@form[:category_id]}
  options={Enum.map(@categories, &{&1.name, &1.id})}
  label="Category"
  prompt="Choose a category"
/>

<%!-- Fixed-width with description --%>
<.phia_select
  field={@form[:timezone]}
  options={@timezones}
  label="Timezone"
  description="Used for scheduling reminders."
  class="w-64"
/>

Attributes

  • field (Phoenix.HTML.FormField) (required) - A Phoenix.HTML.FormField struct obtained via @form[:field_name]. Provides the element id, name, and current value for pre-selection, as well as errors for validation display.

  • options (:list) (required) - The list of options to render. Accepts any format supported by Phoenix.HTML.Form.options_for_select/2:

    • [{"Label", value}, ...] — explicit label/value tuples (most readable)
    • ["value1", "value2"] — plain strings where label equals value
    • [label: "value", ...] — keyword list format
    • Mixed integers and strings are supported as values.

    The currently selected option is determined by comparing each value against field.value.

  • prompt (:string) - When provided, renders a leading <option value=""> as a placeholder. The user sees this text before making a selection. Useful to communicate that a choice is required, e.g. prompt="Select a country...". Submitting with the prompt selected sends an empty string value.

    Defaults to nil.

  • label (:string) - Text rendered in a <label> above the select. Associated via for/id so clicking the label opens the dropdown. When nil, no label is rendered.

    Defaults to nil.

  • description (:string) - Helper text rendered below the label and above the select element. Use for constraints or context, e.g. "This affects all team members." Rendered in text-muted-foreground.

    Defaults to nil.

  • class (:string) - Additional Tailwind CSS classes merged into the <select> element via cn/1. Use to adjust width, font, or other styles. Example: class="w-48" for a fixed-width dropdown.

    Defaults to nil.