Components
Multiple slots
Read time: 3 minutes
Let's recap the solution we used in the previous lesson for the Hero component:
# ...
slot :inner_block, required: true
def hero(assigns) do
  ~H"""
  <div class="bg-gray-800 text-white py-20">
    <div class="container mx-auto text-center">
      <h1 class="text-4xl font-bold"><%= render_slot(@inner_block) %></h1>
      <p class="mt-4 text-lg">My personal website</p>
      <.link
        class="mt-8 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"
        navigate={~p"/other"}
      >
        Get Started
      </.link>
    </div>
  </div>
  """
end
# ...
  
We use the @inner_block slot to render the main text of the page but left two other texts repeated both on the home page and on the /other LiveView. This creates even more confusion because you are already on that page, there is no need for you to see this link.
#Custom slots
By default every component will have an @inner_block slot if there is any HTML inside its tag. However you can also add more slots as needed. Create and run custom_slots.exs:
Mix.install([
  {:liveview_playground, "~> 0.1.5"}
])
defmodule CustomRouter do
  use LiveviewPlaygroundWeb, :router
  pipeline :browser do
    plug :accepts, ["html"]
  end
  scope "/" do
    pipe_through :browser
    live "/", IndexLive, :index
    live "/other", OtherPageLive, :index
  end
end
defmodule CoreComponents do
  use LiveviewPlaygroundWeb, :html
  slot :title
  slot :subtitle
  slot :inner_block
  def hero(assigns) do
    ~H"""
    <div class="bg-gray-800 text-white py-20">
      <div class="container mx-auto text-center">
        <h1 class="text-4xl font-bold"><%= render_slot(@title) %></h1>
        <p class="mt-4 text-lg"><%= render_slot(@subtitle) %></p>
        <%= render_slot(@inner_block) %>
      </div>
    </div>
    """
  end
end
defmodule IndexLive do
  use LiveviewPlaygroundWeb, :live_view
  import CoreComponents
  def render(assigns) do
    ~H"""
    <.hero>
      <:title>IndexLive</:title>
      <:subtitle>Welcometo my personal website!</:subtitle>
      <.link
        class="mt-8 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded"
        navigate={~p"/other"}
      >
        Get Started
      </.link>
    </.hero>
    <.link navigate={~p"/other"}>Go to other</.link>
    """
  end
end
defmodule OtherPageLive do
  use LiveviewPlaygroundWeb, :live_view
  import CoreComponents
  def render(assigns) do
    ~H"""
    <.hero>
      <:title>OtherPageLive</:title>
      <:subtitle>You're on the first step!</:subtitle>
    </.hero>
    <.link navigate={~p"/"}>Go to home</.link>
    """
  end
end
LiveviewPlayground.start(router: CustomRouter, scripts: ["https://cdn.tailwindcss.com"])
  
The first modification we made was to add two new slot to our component definition. To make things clearer we use the names :title and :subtitle for the new slots.
Using custom slots is very similar to component syntax except that you must use :. When we put text in <:my_slot>Abc</:my_slot> the HEEx code inside it will be sent to this named slot as @my_slot. Any HTML not within a named slot will be placed in the @inner_block slot.
The render_slot/2 function can understand when there is nothing in the slot. In the OtherPageLive view we did not add anything outside of named slots and even so there were no problems in the code.
#Recap!
- Components can have more than one slot.
 - 
Named slots can be used as 
<:name>Content</:name>and rendered as<% render_slot(@name) %>. - 
Any HEEx outside of named slots falls into the 
@inner_blockslot. 
Feedback
Got any feedback about this page? Let us know!