Surface - A component-based library for Phoenix LiveView

I wonder if you might help scribble out how you would handle a theoretical “Card” component with optional slots.

So imagine you wanted a final template to look like:

  <Card>
    <Header class="stuff">
      header
    </Header>

    Body text

    <Footer class="footer stuff">
      my footer
    </Footer>
  </Card

So I initially thought to model this as per your example:

defmodule ExampleWeb.Component.Card do
  @moduledoc false

  use ExampleWeb, :surface_component

  slot header

  slot default

  slot footer

  def render(assigns) do
    ~H"""
    <div class="card">
      <div class="@header_class">
        <slot name="header"/>
      </div>
      <div class="body class">
        <slot />
      </div>
      <div class="@footer_class">
        <slot name="footer"/>
      </div>
    </div>
    """
  end
end

But what if we add in the requirement as here that we want to pull the header and footer classes out of the slots and also want to suppress rendering of one of the sections if it’s blank? ie if the header slot is say empty then we render nothing at all

I suppose that the first step is to stop using slots and instead make the header and footer a component so that they can render their own divs, rather than doing it in the Card component? However, is there a different solution?

I’m not quite sure of my use case yet, but I’m thinking about situations where I might have say optional icons or some other attribute and I’m wondering how I might say compute some css class that would depend on whether the icon slot had been filled or not? Can I get your thoughts?

Note, really liking Surface so far! Thanks for creating it!

1 Like