Lavash.Overlay.Modal (Lavash v0.3.0-rc.3)

Copy Markdown View Source

Modal behavior plugin for Lavash Components.

This plugin adds modal-specific state management and rendering to a component:

  • Automatic open/close state with a configurable field name
  • :close action that sets the open field to nil
  • :noop action for backdrop click prevention
  • Helper components for modal chrome

Basic Usage

defmodule MyApp.EditModal do
  use Lavash.Component, extensions: [Lavash.Overlay.Modal.Dsl]
  import Lavash.Overlay.Modal.Helpers  # For modal_chrome and modal_close_button

  modal do
    open_field :product_id  # nil = closed, non-nil = open with ID
  end

  # Your component's state
  read :product, Product do
    id input(:product_id)
  end

  form :edit_form, Product do
    data result(:product)
  end

  actions do
    # Extend the auto-generated :open action with params
    action :open, [:product_id] do
      set :product_id, &(&1.params.product_id)
    end

    action :save do
      submit :edit_form, on_success: :save_success
    end

    action :save_success do
      # :close action is auto-generated by the plugin
      # Just call it or inline the close logic
    end
  end

  # Use render/1 with modal_chrome helper
  # Note: LiveView requires a static root tag, so wrap in div.contents
  def render(assigns) do
    ~H"""
    <div class="contents">
      <.modal_chrome open={@product_id} myself={@myself}>
        <.async_result :let={form} assign={@edit_form}>
          <:loading><div class="p-6">Loading...</div></:loading>
          <div class="p-6">
            <.form for={form} phx-submit="save" phx-target={@myself}>
              ...
            </.form>
          </div>
        </.async_result>
      </.modal_chrome>
    </div>
    """
  end
end

Configuration Options

  • open_field - The field that controls open state (default: :open)
  • close_on_escape - Close when escape is pressed (default: true)
  • close_on_backdrop - Close when clicking backdrop (default: true)
  • max_width - Modal width: :sm, :md, :lg, :xl, :"2xl" (default: :md)

Injected State & Actions

The plugin injects:

  1. Input: input :open_field, :any, from: :ephemeral, default: nil (only if not already defined by user)

  2. Action: :close - Sets the open_field to nil (merged with user-defined :close if present)

  3. Action: :noop - Empty action for preventing event propagation (only if not already defined)

Helper Components

The plugin provides these helper components via Lavash.Overlay.Modal.Helpers:

  • modal_chrome/1 - Renders backdrop, container, escape/click handling
  • modal_close_button/1 - A simple x close button

Import these explicitly with import Lavash.Overlay.Modal.Helpers.