Composable filter UI library for Phoenix LiveView.
Provides builder functions for defining filterable fields that produce
LiveFilter.FilterConfig structs.
Example
filters = [
LiveFilter.text(:search, label: "Search", always_on: true, custom_param: "search"),
LiveFilter.select(:status, label: "Status", options: ~w(pending active shipped)),
LiveFilter.multi_select(:tags, label: "Tags", options: ~w(urgent bug feature)),
LiveFilter.date_range(:inserted_at, label: "Created"),
LiveFilter.boolean(:urgent, label: "Urgent")
]
Summary
Functions
Creates an async select filter config for search-as-you-type selection.
Convenience function component that renders LiveFilter.Bar.
Creates a boolean filter config.
Creates a date filter config.
Creates a date range filter config.
Creates a datetime filter config.
Creates a datetime range filter config.
Parses URL params into filter state using the provided config.
Initializes LiveFilter state on a socket.
Creates a multi-select filter config.
Creates a number filter config.
Parses pagination from URL params using PostgREST limit/offset parameters.
Convenience function component that renders LiveFilter.Paginator.
Creates a radio group filter config.
Creates a single-select filter config.
Creates a text filter config.
Builds a path with raw (non-encoded) query string from a params map.
Functions
@spec async_select( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates an async select filter config for search-as-you-type selection.
Default operators: [:eq], default: :eq.
Requires :search_fn and :load_label_fn callbacks.
Callbacks
:search_fn-fn(query, context) -> [{value, label}]— called when user types in the dropdown:load_label_fn-fn(value, context) -> {:ok, label} | :error— called to resolve display label from a stored value (e.g., on URL reload)
Options
:min_chars- Minimum characters before searching (default: 1):debounce- Debounce delay in ms (default: 200):placeholder- Search input placeholder (default: "Search..."):empty_message- Message when no results found (default: "No results found")
Convenience function component that renders LiveFilter.Bar.
Options
:mode- Filter display mode::basic(default) or:command:theme- Theme preset::default,:minimal, or:bordered:variant- Chip border style::outline(default),:ghost,:soft, or custom class string
Example
<LiveFilter.bar filter={@livefilter} />
<LiveFilter.bar filter={@livefilter} mode={:command} />
<LiveFilter.bar filter={@livefilter} mode={:command} theme={:bordered} />
<LiveFilter.bar filter={@livefilter} variant={:ghost} />Attributes
filter(:map) (required)mode(:atom) - Defaults to:basic.theme(:atom) - Defaults to:default.variant(:atom) - Chip border style: :outline (default), :ghost, or :soft. Defaults to:outline.
@spec boolean( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a boolean filter config.
Default operators: [:is], default: :is.
Options
:true_label- Label for true state (default: "Yes"):false_label- Label for false state (default: "No"):any_label- Label for null/any state (default: "Any"):nullable- Enable 3-state (true/false/any) mode (default: false)
@spec date( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a date filter config.
Default operators: [:eq, :gt, :gte, :lt, :lte], default: :eq.
@spec date_range( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a date range filter config.
Default operators: [:gte_lte], default: :gte_lte.
Use this for :date schema fields. For :utc_datetime or :utc_datetime_usec
fields, use datetime_range/2 instead.
@spec datetime( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a datetime filter config.
Default operators: [:eq, :gt, :gte, :lt, :lte], default: :eq.
Options
:time_format- Time display format::twelve_hour(default) or:twenty_four_hour:minute_step- Minute increment step: 1 (default), 5, 15, or 30
@spec datetime_range( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a datetime range filter config.
Default operators: [:gte_lte], default: :gte_lte.
Similar to date_range/2 but generates full ISO8601 datetime values with
start-of-day (00:00:00Z) and end-of-day (23:59:59Z) times. Use this for
:utc_datetime or :utc_datetime_usec schema fields.
@spec from_params(map(), [LiveFilter.FilterConfig.t()]) :: {[LiveFilter.Filter.t()], map()}
Parses URL params into filter state using the provided config.
Returns {filters, remaining_params}.
@spec init( Phoenix.LiveView.Socket.t(), [LiveFilter.FilterConfig.t()], [LiveFilter.Filter.t()], keyword() ) :: Phoenix.LiveView.Socket.t()
Initializes LiveFilter state on a socket.
Assigns :livefilter with config, filters, and a unique ID.
Accepts an optional context: keyword that is stored and passed to async_select callbacks.
@spec multi_select( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a multi-select filter config.
Default operators: [:cs, :ov], default: :cs.
Requires :options or :options_fn.
Note: Uses array containment operators for Postgres array columns:
:cs- contains (@>) - array contains all selected values:ov- overlaps (&&) - array contains any of the selected values
@spec number( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a number filter config.
Default operators: [:eq, :neq, :gt, :gte, :lt, :lte], default: :eq.
@spec pagination_from_params( map(), keyword() ) :: {LiveFilter.Pagination.t(), map()}
Parses pagination from URL params using PostgREST limit/offset parameters.
Returns {pagination, remaining_params}.
Options
:default_limit- Default items per page (default: 25):max_limit- Maximum allowed limit value (default: 100):limit_options- Available per-page options for UI dropdown (default: [10, 25, 50, 100])
Example
{pagination, remaining} = LiveFilter.pagination_from_params(params, default_limit: 25)
# pagination.limit => 25
# pagination.offset => 0
# With URL ?limit=50&offset=100
{pagination, remaining} = LiveFilter.pagination_from_params(%{"limit" => "50", "offset" => "100"})
# pagination.limit => 50
# pagination.offset => 100
Convenience function component that renders LiveFilter.Paginator.
Example
<LiveFilter.paginator pagination={@pagination} />
<LiveFilter.paginator pagination={@pagination} class="mt-4" />Attributes
pagination(LiveFilter.Pagination) (required)class(:string) - Defaults to"".
@spec radio_group( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a radio group filter config.
Default operators: [:eq], default: :eq.
Requires :options or :options_fn.
Options
:style- Display style::pills(default) or:radios:inline_threshold- Max options to show inline as pills (default: 4):options- List of options (required)
@spec select( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a single-select filter config.
Default operators: [:eq, :neq], default: :eq.
Requires :options or :options_fn.
@spec text( atom(), keyword() ) :: LiveFilter.FilterConfig.t()
Creates a text filter config.
Default operators: [:ilike, :eq, :neq, :like], default: :ilike.
Builds a path with raw (non-encoded) query string from a params map.
Use this instead of ~p"/path?#{params}" to avoid percent-encoding
special characters like {, }, and ,.
Example
# In handle_info:
path = LiveFilter.to_path("/tasks", all_params)
{:noreply, push_patch(socket, to: path)}
# Produces: /tasks?tags=ov.{testing,bug}
# Instead of: /tasks?tags=ov.%7Btesting%2Cbug%7D