Behaviour for UI component adapters.
Implement this behaviour to integrate any UI library:
- Plain Tailwind CSS (default,
MishkaGervaz.UIAdapters.Tailwind) - A custom component library
- Database-driven dynamic components
- Anything else with the same per-component shape
Using the macro
use MishkaGervaz.Behaviours.UIAdapter provides default implementations
that delegate to a fallback module (Tailwind by default). Override only
the components you need:
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter
# Override specific components — everything else uses Tailwind defaults.
def button(assigns), do: MyAppWeb.Components.Button.button(assigns)
endWith a components module
Pass your components module to auto-generate overrides for any function it exports:
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
components: MyAppWeb.Components
endWith a custom fallback
Use a different fallback module instead of Tailwind:
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
fallback: MyAppWeb.Components.Base,
components: MyAppWeb.Components.Custom
endDSL usage
presentation do
ui_adapter MyAppWeb.UIAdapter
end
Summary
Types
Phoenix LiveView assigns map passed to every component function.
A {function_name, docstring} pair.
Callbacks
Render a static alert/notice (info/warning/error/success/neutral)
Render archive status toggle
Render a container for array-of-maps fields
Render a badge/tag
Render bulk actions bar container
Render individual bulk action button
Render a button
Render array/list container
Render code/monospace cell value
Render date cell value
Render datetime cell value
Render empty cell value (nil/missing data)
Render number cell value
Render text cell value
Render a checkbox
Render a combobox (text input with dropdown suggestions)
Render a date input
Render a date range container
Render a datetime input
Render a dropdown menu
Render empty state
Render error state
Render a field error message display
Render a collapsible group of fields
Render a field wrapper with label, input, and error display
Render filter reset/clear button
Render the main form wrapper (phx-change, phx-submit)
Render a form footer (static content below the submit row)
Render a form header (title + description)
Render an icon
Render a JSON editor (textarea with formatting)
Render a single-select with paginated load-more (no search input)
Render loading state
Render a multi-select with search support
Render a navigation link
Render a container for nested form fields
Render a number input
Render pagination container with page info
Render pagination nav button (prev/next/first/last)
Render pagination page number button
Render a password input (masked text entry)
Render a range slider input
Render a single-select with search support
Render a select dropdown
Render a loading spinner
Render wizard/tabs step progress indicator
Render wizard prev/next/submit navigation controls
Render a dynamic string list input with add/remove buttons
Render table wrapper
Render table header row
Render a table cell
Render template switcher container with buttons
Render template switcher button
Render a text input
Render a multi-line text input
Render a table header cell
Render a boolean toggle switch
Render a table row
Render a drag-drop file upload zone
Render an existing file card with remove button (for edit mode)
Render a styled file input (non-dropzone) upload control
Render a file preview thumbnail
Render an upload progress bar
Functions
Sets up an adapter that delegates every component to a fallback module,
and optionally overrides specific components from a :components module.
The list of every component function name on the behaviour. Useful for introspection and for tests that want to assert all functions are wired.
Resolves the {module, function} target a generated override should call,
given the consuming module's :components, :nested_components,
:module_prefix, and :component_prefix options.
Types
Callbacks
@callback alert(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a static alert/notice (info/warning/error/success/neutral)
@callback archive_toggle(assigns()) :: Phoenix.LiveView.Rendered.t()
Render archive status toggle
@callback array_fields(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a container for array-of-maps fields
@callback badge(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a badge/tag
@callback bulk_action_bar(assigns()) :: Phoenix.LiveView.Rendered.t()
Render bulk actions bar container
@callback bulk_action_button(assigns()) :: Phoenix.LiveView.Rendered.t()
Render individual bulk action button
@callback button(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a button
@callback cell_array(assigns()) :: Phoenix.LiveView.Rendered.t()
Render array/list container
@callback cell_code(assigns()) :: Phoenix.LiveView.Rendered.t()
Render code/monospace cell value
@callback cell_date(assigns()) :: Phoenix.LiveView.Rendered.t()
Render date cell value
@callback cell_datetime(assigns()) :: Phoenix.LiveView.Rendered.t()
Render datetime cell value
@callback cell_empty(assigns()) :: Phoenix.LiveView.Rendered.t()
Render empty cell value (nil/missing data)
@callback cell_number(assigns()) :: Phoenix.LiveView.Rendered.t()
Render number cell value
@callback cell_text(assigns()) :: Phoenix.LiveView.Rendered.t()
Render text cell value
@callback checkbox(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a checkbox
@callback combobox(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a combobox (text input with dropdown suggestions)
@callback date_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a date input
@callback date_range_container(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a date range container
@callback datetime_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a datetime input
@callback dropdown(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a dropdown menu
@callback empty_state(assigns()) :: Phoenix.LiveView.Rendered.t()
Render empty state
@callback error_state(assigns()) :: Phoenix.LiveView.Rendered.t()
Render error state
@callback field_error(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a field error message display
@callback field_group(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a collapsible group of fields
@callback field_wrapper(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a field wrapper with label, input, and error display
@callback filter_reset_button(assigns()) :: Phoenix.LiveView.Rendered.t()
Render filter reset/clear button
@callback form_container(assigns()) :: Phoenix.LiveView.Rendered.t()
Render the main form wrapper (phx-change, phx-submit)
@callback form_header(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a form header (title + description)
@callback icon(assigns()) :: Phoenix.LiveView.Rendered.t()
Render an icon
@callback json_editor(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a JSON editor (textarea with formatting)
@callback load_more_select(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a single-select with paginated load-more (no search input)
@callback loading_state(assigns()) :: Phoenix.LiveView.Rendered.t()
Render loading state
@callback multi_select(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a multi-select with search support
@callback nested_fields(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a container for nested form fields
@callback number_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a number input
@callback pagination_container(assigns()) :: Phoenix.LiveView.Rendered.t()
Render pagination container with page info
@callback pagination_page_button(assigns()) :: Phoenix.LiveView.Rendered.t()
Render pagination page number button
@callback password_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a password input (masked text entry)
@callback range_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a range slider input
@callback search_select(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a single-select with search support
@callback select(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a select dropdown
@callback spinner(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a loading spinner
@callback step_indicator(assigns()) :: Phoenix.LiveView.Rendered.t()
Render wizard/tabs step progress indicator
@callback string_list_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a dynamic string list input with add/remove buttons
@callback table(assigns()) :: Phoenix.LiveView.Rendered.t()
Render table wrapper
@callback table_header(assigns()) :: Phoenix.LiveView.Rendered.t()
Render table header row
@callback td(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a table cell
@callback template_switcher(assigns()) :: Phoenix.LiveView.Rendered.t()
Render template switcher container with buttons
@callback template_switcher_button(assigns()) :: Phoenix.LiveView.Rendered.t()
Render template switcher button
@callback text_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a text input
@callback textarea(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a multi-line text input
@callback th(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a table header cell
@callback toggle_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a boolean toggle switch
@callback tr(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a table row
@callback upload_dropzone(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a drag-drop file upload zone
@callback upload_existing_file(assigns()) :: Phoenix.LiveView.Rendered.t()
Render an existing file card with remove button (for edit mode)
@callback upload_file_input(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a styled file input (non-dropzone) upload control
@callback upload_preview(assigns()) :: Phoenix.LiveView.Rendered.t()
Render a file preview thumbnail
@callback upload_progress(assigns()) :: Phoenix.LiveView.Rendered.t()
Render an upload progress bar
Functions
Sets up an adapter that delegates every component to a fallback module,
and optionally overrides specific components from a :components module.
Options
:fallback— module providing the default implementations. Defaults toMishkaGervaz.UIAdapters.Tailwind.:components— module to source overrides from. Each component function is wired only when the target module is loaded and exports the corresponding 1-arity function.:nested_components— whentrue, look for each component under a submodule (e.g.Components.Button.button/1). Whenfalse(default), the components module is flat (e.g.Components.button/1).:module_prefix— a string prepended to each submodule name whennested_components: true. Example:"Mishka"makes the macro look underComponents.MishkaButton.button/1.:component_prefix— a string prepended to each function name. Example:"mc_"makes the macro look upmc_button/1on the target module.
Examples
# All defaults from Tailwind
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter
end
# Flat components module — Components.button/1
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
components: MyAppWeb.Components
end
# Nested style — Components.Button.button/1
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
components: MyAppWeb.Components,
nested_components: true
end
# Module prefix — Components.MishkaButton.button/1
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
components: MyAppWeb.Components,
nested_components: true,
module_prefix: "Mishka"
end
# Function prefix — Components.mc_button/1
defmodule MyAppWeb.UIAdapter do
use MishkaGervaz.Behaviours.UIAdapter,
components: MyAppWeb.Components,
component_prefix: "mc_"
end
@spec component_functions() :: [atom()]
The list of every component function name on the behaviour. Useful for introspection and for tests that want to assert all functions are wired.
@spec resolve_target(atom(), module(), boolean(), String.t() | nil, String.t() | nil) :: {module(), atom()}
Resolves the {module, function} target a generated override should call,
given the consuming module's :components, :nested_components,
:module_prefix, and :component_prefix options.
Public so the macro can call it; also useful for testing the routing logic directly without having to build a full adapter.