Packages

Composable, URL-driven filtering for Phoenix LiveView with Linear/Notion-style filters and PostgREST-compatible parameters.

Current section

Files

Jump to
livefilter lib live_filter theme.ex
Raw

lib/live_filter/theme.ex

defmodule LiveFilter.Theme do
@moduledoc """
Theme definitions for LiveFilter command-style filter chips.
Provides three preset themes: `:default`, `:minimal`, and `:bordered`.
Each theme defines CSS classes for different chip elements.
## Usage
LiveFilter.Theme.get(:default, :chip)
# => "inline-flex items-center bg-base-100 border border-base-300 rounded-lg h-8"
## Custom Themes
You can pass custom class overrides via the filter config or bar assigns.
"""
# Using DaisyUI btn classes ensures consistent height/styling in host apps
# since DaisyUI classes are generated by the plugin regardless of content scanning
# Base chip class uses btn btn-sm; the variant (outline/ghost/soft) is applied separately
# via the variant attribute passed to the bar component
@themes %{
default: %{
chip: "btn btn-sm gap-0 px-0 font-normal",
field: "flex items-center gap-1.5 px-2.5 border-r border-base-300",
operator:
"px-2 text-base-content/70 hover:text-base-content hover:bg-base-200 rounded cursor-pointer",
values: "flex items-center gap-1 px-2",
badge: "badge badge-sm gap-1",
remove: "px-2 opacity-60 hover:opacity-100 cursor-pointer",
icon: ""
},
minimal: %{
chip: "btn btn-sm gap-0 px-0 font-normal",
field: "flex items-center gap-1.5 px-2",
operator: "px-1.5 text-base-content/50 hover:text-base-content cursor-pointer",
values: "flex items-center gap-1 px-1.5",
badge: "text-sm",
remove: "px-1.5 opacity-60 hover:opacity-100 cursor-pointer",
icon: ""
},
bordered: %{
chip: "btn btn-sm btn-primary gap-0 px-0 font-normal",
field: "flex items-center gap-1.5 px-2.5 border-r border-primary/20",
operator:
"px-2 text-primary/70 hover:text-primary hover:bg-primary/10 rounded cursor-pointer",
values: "flex items-center gap-1 px-2",
badge: "badge badge-primary badge-sm gap-1",
remove: "px-2 opacity-60 hover:opacity-100 cursor-pointer",
icon: ""
},
# Neutral theme: no DaisyUI btn classes, uses theme-aware utilities
# Works seamlessly with light/dark themes without CSS overrides
neutral: %{
chip:
"inline-flex items-center h-8 text-sm gap-0 px-0 font-normal bg-base-100 border border-base-300 rounded-lg text-base-content hover:bg-base-200 transition-colors",
field: "flex items-center gap-1.5 px-2.5 border-r border-base-300",
operator:
"px-2 text-base-content/70 hover:text-base-content hover:bg-base-200 rounded cursor-pointer",
values: "flex items-center gap-1 px-2",
badge: "badge badge-soft badge-sm gap-1 rounded",
remove: "px-2 opacity-60 hover:opacity-100 cursor-pointer",
icon: ""
}
}
@doc """
Gets a CSS class string for the given theme and element.
## Elements
- `:chip` - The outer chip container
- `:field` - The field label section with icon
- `:operator` - The operator dropdown trigger
- `:values` - The values/badges section
- `:badge` - Individual value badges
- `:remove` - Remove button (both value and filter)
- `:icon` - Default icon styling
## Examples
iex> LiveFilter.Theme.get(:default, :chip)
"inline-flex items-center bg-base-100 border border-base-300 rounded-lg h-8 text-sm"
iex> LiveFilter.Theme.get(:bordered, :badge)
"badge badge-primary badge-sm gap-1"
"""
@spec get(atom(), atom()) :: String.t()
def get(theme_name, element) when is_atom(theme_name) and is_atom(element) do
@themes[theme_name][element] || @themes[:default][element] || ""
end
@doc """
Returns the list of available theme names.
"""
@spec available_themes() :: [atom()]
def available_themes, do: Map.keys(@themes)
@doc """
Returns all classes for a given theme.
"""
@spec get_theme(atom()) :: map()
def get_theme(theme_name) do
@themes[theme_name] || @themes[:default]
end
end