Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Minimal Bug Repro Temple<>LiveComponent Example

minimal-bug-repro-temple-livecomponent-example.livemd

Minimal Bug Repro Temple<>LiveComponent Example

Mix.install([
  {:phoenix_playground, "~> 0.1.6"},
  {:temple, "~> 0.14.0"},
], [
  config: [
    temple: [
      engine: Phoenix.LiveView.Engine
    ]
  ]
])

Section

defmodule DemoLive.Components.TestLiveComponent do
  use Phoenix.LiveComponent

  import Temple
  import Phoenix.LiveView.TagEngine, only: [component: 3, inner_block: 2]

  def render(assigns) do
    temple do
      div do: "TEST LIVE COMPONENT CONTENT"
    end
  end
end

defmodule DemoLive.CoreComponents do
  use Phoenix.Component

  alias Phoenix.LiveView.JS

  attr :id, :string, required: true
  attr :show, :boolean, default: false
  attr :on_cancel, JS, default: %JS{}
  slot :inner_block, required: true

  def modal(assigns) do
    ~H"""
    
      
      
        
          
            
              <%= render_slot(@inner_block) %>
            
          
        
      
    
    """
  end

  def show(js \\ %JS{}, selector) do
    JS.show(js,
      to: selector,
      time: 300,
      transition:
        {"transition-all transform ease-out duration-300",
         "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
         "opacity-100 translate-y-0 sm:scale-100"}
    )
  end

  def hide(js \\ %JS{}, selector) do
    JS.hide(js,
      to: selector,
      time: 200,
      transition:
        {"transition-all transform ease-in duration-200",
         "opacity-100 translate-y-0 sm:scale-100",
         "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"}
    )
  end

  def show_modal(js \\ %JS{}, id) when is_binary(id) do
    js
    |> JS.show(to: "##{id}")
    |> JS.show(
      to: "##{id}-bg",
      time: 300,
      transition: {"transition-all transform ease-out duration-300", "opacity-0", "opacity-100"}
    )
    |> show("##{id}-container")
    |> JS.add_class("overflow-hidden", to: "body")
    |> JS.focus_first(to: "##{id}-content")
  end

  def hide_modal(js \\ %JS{}, id) do
    js
    |> JS.hide(
      to: "##{id}-bg",
      transition: {"transition-all transform ease-in duration-200", "opacity-100", "opacity-0"}
    )
    |> hide("##{id}-container")
    |> JS.hide(to: "##{id}", transition: {"block", "block", "hidden"})
    |> JS.remove_class("overflow-hidden", to: "body")
    |> JS.pop_focus()
  end
end

defmodule DemoLive do
  use Phoenix.LiveView

  import Temple
  import Phoenix.LiveView.TagEngine, only: [component: 3, inner_block: 2]
  import DemoLive.CoreComponents

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def render(assigns) do
    temple do
      button "phx-click": show_modal("test-modal"), do: "Show test modal"
      c &amp;modal/1, id: "test-modal" do
        c &amp;live_component/1,
          id: "test-live-component",
          module: DemoLive.Components.TestLiveComponent
      end
    end
  end

  # def render(assigns) do
  #   temple do
  #     button "phx-click": show_modal("test-modal"), do: "Show test modal"
  #     ~H"""
  #     <.modal id="test-modal">
  #       <.live_component
  #         id="test-live-component"
  #         module={DemoLive.Components.TestLiveComponent}
  #       />
  #     
  #     """
  #   end
  # end
end

PhoenixPlayground.start(live: DemoLive)