PhiaUi.Components.FilterBar (phia_ui v0.1.12)

Copy Markdown View Source

FilterBar component for PhiaUI.

A horizontal toolbar for composing table and list filters. Combines a full-text search input, labelled select dropdowns, checkbox toggles, and a reset button into a cohesive, accessible filter UI.

Each sub-component is independently usable — you can mix and match them in any combination above a data_grid/1 or table/1.

When to use

Use FilterBar for "simple" filter scenarios where users can select from predefined options or type a search query. For power users who need to build complex multi-condition queries (AND/OR, operators), use FilterBuilder instead.

Anatomy

ComponentElementPurpose
filter_bar/1divFlex row wrapper for all filter sub-components
filter_search/1inputFull-text search with magnifier icon
filter_select/1selectLabelled native dropdown for enum filters
filter_toggle/1inputCheckbox toggle for boolean filters
filter_reset/1buttonClear all active filters

Complete example — user management table

<.filter_bar>
  <.filter_search
    placeholder="Search by name or email…"
    on_search="search_users"
    value={@search_query}
  />
  <.filter_select
    label="Role"
    name="role"
    options={[
      {"All roles", ""},
      {"Admin", "admin"},
      {"Editor", "editor"},
      {"Viewer", "viewer"}
    ]}
    value={@filter_role}
    on_change="filter_role"
  />
  <.filter_select
    label="Status"
    name="status"
    options={[{"All", ""}, {"Active", "active"}, {"Suspended", "suspended"}]}
    value={@filter_status}
    on_change="filter_status"
  />
  <.filter_toggle
    label="Show archived"
    name="archived"
    checked={@show_archived}
    on_change="toggle_archived"
  />
  <.filter_reset on_click="reset_filters" />
</.filter_bar>

LiveView handlers

def handle_event("search_users", %{"value" => q}, socket) do
  {:noreply, assign(socket, search_query: q)}
end

def handle_event("filter_role", %{"role" => role}, socket) do
  {:noreply, assign(socket, filter_role: role)}
end

def handle_event("filter_status", %{"status" => status}, socket) do
  {:noreply, assign(socket, filter_status: status)}
end

def handle_event("toggle_archived", %{"archived" => checked}, socket) do
  {:noreply, assign(socket, show_archived: checked == "true")}
end

def handle_event("reset_filters", _params, socket) do
  {:noreply, assign(socket,
    search_query: "",
    filter_role: "",
    filter_status: "",
    show_archived: false
  )}
end

Pair filter_search/1 with phx-debounce on the input to avoid a server round-trip on every keystroke:

<.filter_search
  on_search="search_users"
  value={@query}
  rest={%{"phx-debounce" => "300"}}
/>

Summary

Functions

Renders the filter bar container.

Renders a reset / clear-all button for the filter bar.

Renders a full-text search input with a magnifier icon.

Renders a labelled native select dropdown.

Renders a checkbox toggle with a visible inline label.

Functions

filter_bar(assigns)

Renders the filter bar container.

A flex-wrap row that holds all filter sub-components. The flex-wrap means filters gracefully reflow to a second line on smaller screens.

Typically placed directly above a data_grid/1 or table/1:

<.filter_bar class="mb-4">
  <.filter_search ... />
  <.filter_select ... />
</.filter_bar>
<.data_grid rows={@filtered_rows} columns={@columns} />

Attributes

  • class (:string) - Additional CSS classes for the root wrapper. Defaults to nil.
  • Global attributes are accepted. HTML attributes forwarded to the root div.

Slots

filter_reset(assigns)

Renders a reset / clear-all button for the filter bar.

Fires on_click via phx-click. The handler should reset all filter assigns to their defaults (empty string, false, nil) and re-apply the query.

Example

<.filter_reset on_click="reset_filters" />

# Or with a custom label
<.filter_reset on_click="clear_all" label="Clear all filters" />

# LiveView handler
def handle_event("reset_filters", _params, socket) do
  {:noreply, assign(socket, query: "", status: "", archived: false)}
end

Attributes

  • on_click (:string) (required) - phx-click event name fired when the reset button is pressed. The LiveView handler should reset all filter assigns to their default values.

  • label (:string) - Button label text. Defaults to "Reset" when nil. Defaults to nil.

  • class (:string) - Additional CSS classes for the button. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the <button> element.

filter_search(assigns)

Renders a full-text search input with a magnifier icon.

Fires on_search via phx-change on every keystroke. Add phx-debounce to your LiveView form or via :rest to debounce.

Example

<.filter_search
  placeholder="Search invoices…"
  on_search="search_invoices"
  value={@search_query}
/>

Attributes

  • placeholder (:string) - Input placeholder text shown when the field is empty. Defaults to "Search…".

  • on_search (:string) (required) - phx-change event name fired on every keystroke. The LiveView receives %{"search" => query} (or whatever :name is set to). Add phx-debounce="300" via :rest to reduce server round-trips.

  • value (:string) - Controlled value — pass the current search query assign from the LiveView. Defaults to "".

  • name (:string) - Input name attribute — the param key the LiveView receives on phx-change. Defaults to "search".

  • class (:string) - Additional CSS classes for the input wrapper. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the input wrapper div (e.g. phx-debounce="300").

filter_select(assigns)

Renders a labelled native select dropdown.

The label is rendered as muted text to the left of the <select>. Native <select> elements are used (not custom dropdowns) to preserve browser accessibility, mobile behaviour, and keyboard navigation for free.

Example

<.filter_select
  label="Priority"
  name="priority"
  options={[{"All", ""}, {"Critical", "critical"}, {"High", "high"}, {"Low", "low"}]}
  value={@filter_priority}
  on_change="filter_priority"
/>

Attributes

  • label (:string) (required) - Visible label rendered to the left of the dropdown (e.g. "Status", "Role").

  • name (:string) (required) - Select name attribute — the param key the LiveView receives on phx-change.

  • options (:list) (required) - List of {label, value} tuples rendered as <option> elements. Convention: {"All", ""} as the first option clears the filter.

    options={[{"All", ""}, {"Active", "active"}, {"Inactive", "inactive"}]}
  • value (:string) - Currently selected value — used to set the selected attribute on the matching option. Defaults to "".

  • on_change (:string) (required) - phx-change event name fired when the user changes the selection. The LiveView receives %{name => value} where name is :name.

  • class (:string) - Additional CSS classes for the wrapper div. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the wrapper div.

filter_toggle(assigns)

Renders a checkbox toggle with a visible inline label.

Fires on_change via phx-change when the checkbox state changes. The entire label text is clickable (clicking the text toggles the checkbox).

Example

<.filter_toggle
  label="My tasks only"
  name="mine_only"
  checked={@mine_only}
  on_change="toggle_mine_only"
/>

# LiveView handler
def handle_event("toggle_mine_only", %{"mine_only" => v}, socket) do
  {:noreply, assign(socket, mine_only: v == "true")}
end

Attributes

  • label (:string) (required) - Label text displayed beside the checkbox (e.g. "Show archived", "Mine only").

  • name (:string) (required) - Checkbox name attribute — the param key the LiveView receives.

  • checked (:boolean) - Whether the checkbox is currently checked — bind to a LiveView boolean assign. Defaults to false.

  • on_change (:string) (required) - phx-change event name. The LiveView receives %{name => "true" | "false"}. Note: HTML checkbox values are strings, so compare with == "true".

  • class (:string) - Additional CSS classes for the label element. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the <label> wrapper element.