MishkaGervaz.Behaviours.UIAdapter behaviour (MishkaGervaz v0.0.1-alpha.2)

Copy Markdown View Source

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)
end

With 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
end

With 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
end

DSL 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

assigns()

@type assigns() :: map()

Phoenix LiveView assigns map passed to every component function.

component()

@type component() :: {atom(), String.t()}

A {function_name, docstring} pair.

Callbacks

alert(assigns)

(optional)
@callback alert(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a static alert/notice (info/warning/error/success/neutral)

archive_toggle(assigns)

(optional)
@callback archive_toggle(assigns()) :: Phoenix.LiveView.Rendered.t()

Render archive status toggle

array_fields(assigns)

(optional)
@callback array_fields(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a container for array-of-maps fields

badge(assigns)

(optional)
@callback badge(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a badge/tag

bulk_action_bar(assigns)

(optional)
@callback bulk_action_bar(assigns()) :: Phoenix.LiveView.Rendered.t()

Render bulk actions bar container

bulk_action_button(assigns)

(optional)
@callback bulk_action_button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render individual bulk action button

button(assigns)

(optional)
@callback button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a button

cell_array(assigns)

(optional)
@callback cell_array(assigns()) :: Phoenix.LiveView.Rendered.t()

Render array/list container

cell_code(assigns)

(optional)
@callback cell_code(assigns()) :: Phoenix.LiveView.Rendered.t()

Render code/monospace cell value

cell_date(assigns)

(optional)
@callback cell_date(assigns()) :: Phoenix.LiveView.Rendered.t()

Render date cell value

cell_datetime(assigns)

(optional)
@callback cell_datetime(assigns()) :: Phoenix.LiveView.Rendered.t()

Render datetime cell value

cell_empty(assigns)

(optional)
@callback cell_empty(assigns()) :: Phoenix.LiveView.Rendered.t()

Render empty cell value (nil/missing data)

cell_number(assigns)

(optional)
@callback cell_number(assigns()) :: Phoenix.LiveView.Rendered.t()

Render number cell value

cell_text(assigns)

(optional)
@callback cell_text(assigns()) :: Phoenix.LiveView.Rendered.t()

Render text cell value

checkbox(assigns)

(optional)
@callback checkbox(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a checkbox

combobox(assigns)

(optional)
@callback combobox(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a combobox (text input with dropdown suggestions)

date_input(assigns)

(optional)
@callback date_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a date input

date_range_container(assigns)

(optional)
@callback date_range_container(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a date range container

datetime_input(assigns)

(optional)
@callback datetime_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a datetime input

dropdown(assigns)

(optional)
@callback dropdown(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a dropdown menu

empty_state(assigns)

(optional)
@callback empty_state(assigns()) :: Phoenix.LiveView.Rendered.t()

Render empty state

error_state(assigns)

(optional)
@callback error_state(assigns()) :: Phoenix.LiveView.Rendered.t()

Render error state

field_error(assigns)

(optional)
@callback field_error(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a field error message display

field_group(assigns)

(optional)
@callback field_group(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a collapsible group of fields

field_wrapper(assigns)

(optional)
@callback field_wrapper(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a field wrapper with label, input, and error display

filter_reset_button(assigns)

(optional)
@callback filter_reset_button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render filter reset/clear button

form_container(assigns)

(optional)
@callback form_container(assigns()) :: Phoenix.LiveView.Rendered.t()

Render the main form wrapper (phx-change, phx-submit)

form_footer(assigns)

(optional)
@callback form_footer(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a form footer (static content below the submit row)

form_header(assigns)

(optional)
@callback form_header(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a form header (title + description)

icon(assigns)

(optional)
@callback icon(assigns()) :: Phoenix.LiveView.Rendered.t()

Render an icon

json_editor(assigns)

(optional)
@callback json_editor(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a JSON editor (textarea with formatting)

load_more_select(assigns)

(optional)
@callback load_more_select(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a single-select with paginated load-more (no search input)

loading_state(assigns)

(optional)
@callback loading_state(assigns()) :: Phoenix.LiveView.Rendered.t()

Render loading state

multi_select(assigns)

(optional)
@callback multi_select(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a multi-select with search support

nav_link(assigns)

(optional)
@callback nav_link(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a navigation link

nested_fields(assigns)

(optional)
@callback nested_fields(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a container for nested form fields

number_input(assigns)

(optional)
@callback number_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a number input

pagination_container(assigns)

(optional)
@callback pagination_container(assigns()) :: Phoenix.LiveView.Rendered.t()

Render pagination container with page info

pagination_nav_button(assigns)

(optional)
@callback pagination_nav_button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render pagination nav button (prev/next/first/last)

pagination_page_button(assigns)

(optional)
@callback pagination_page_button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render pagination page number button

password_input(assigns)

(optional)
@callback password_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a password input (masked text entry)

range_input(assigns)

(optional)
@callback range_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a range slider input

search_select(assigns)

(optional)
@callback search_select(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a single-select with search support

select(assigns)

(optional)
@callback select(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a select dropdown

spinner(assigns)

(optional)
@callback spinner(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a loading spinner

step_indicator(assigns)

(optional)
@callback step_indicator(assigns()) :: Phoenix.LiveView.Rendered.t()

Render wizard/tabs step progress indicator

step_navigation(assigns)

(optional)
@callback step_navigation(assigns()) :: Phoenix.LiveView.Rendered.t()

Render wizard prev/next/submit navigation controls

string_list_input(assigns)

(optional)
@callback string_list_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a dynamic string list input with add/remove buttons

table(assigns)

(optional)
@callback table(assigns()) :: Phoenix.LiveView.Rendered.t()

Render table wrapper

table_header(assigns)

(optional)
@callback table_header(assigns()) :: Phoenix.LiveView.Rendered.t()

Render table header row

td(assigns)

(optional)
@callback td(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a table cell

template_switcher(assigns)

(optional)
@callback template_switcher(assigns()) :: Phoenix.LiveView.Rendered.t()

Render template switcher container with buttons

template_switcher_button(assigns)

(optional)
@callback template_switcher_button(assigns()) :: Phoenix.LiveView.Rendered.t()

Render template switcher button

text_input(assigns)

(optional)
@callback text_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a text input

textarea(assigns)

(optional)
@callback textarea(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a multi-line text input

th(assigns)

(optional)
@callback th(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a table header cell

toggle_input(assigns)

(optional)
@callback toggle_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a boolean toggle switch

tr(assigns)

(optional)
@callback tr(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a table row

upload_dropzone(assigns)

(optional)
@callback upload_dropzone(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a drag-drop file upload zone

upload_existing_file(assigns)

(optional)
@callback upload_existing_file(assigns()) :: Phoenix.LiveView.Rendered.t()

Render an existing file card with remove button (for edit mode)

upload_file_input(assigns)

(optional)
@callback upload_file_input(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a styled file input (non-dropzone) upload control

upload_preview(assigns)

(optional)
@callback upload_preview(assigns()) :: Phoenix.LiveView.Rendered.t()

Render a file preview thumbnail

upload_progress(assigns)

(optional)
@callback upload_progress(assigns()) :: Phoenix.LiveView.Rendered.t()

Render an upload progress bar

Functions

__using__(opts \\ [])

(macro)

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 to MishkaGervaz.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 — when true, look for each component under a submodule (e.g. Components.Button.button/1). When false (default), the components module is flat (e.g. Components.button/1).

  • :module_prefix — a string prepended to each submodule name when nested_components: true. Example: "Mishka" makes the macro look under Components.MishkaButton.button/1.

  • :component_prefix — a string prepended to each function name. Example: "mc_" makes the macro look up mc_button/1 on 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

component_functions()

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

resolve_target(func, components, nested?, module_prefix, component_prefix)

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