# `PhiaUi.Components.Select`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/inputs/select.ex#L1)

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.

# `phia_select`

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`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
