Phoenix.Component usage - getting warning: undefined slot “label” for component MyAppWeb.CoreComponents.input/1

Hello there,

in my current Phoenix app I extended the built-in CoreComponents module with a custom radio-card input component which renders the following TailwindUI inspired UI:

However because I needed both the label and description to accept HTML, I did the following:

defguard is_slot(attrs) when is_list(attrs) and is_map(hd(attrs)) and is_map_key(hd(attrs), :__slot__)

In the HEEX template I use the following snippet:

<%= if is_slot(@label) do %>
  <%= render_slot(@label) %>
<% else %>
  <span><%= @label %></span>
<% end %>

This works quite fine with the code in CoreComponents.input/1, however it still spits out a warning besides working as expected:

attr :label, :string, default: nil
attr :description, :string, default: nil

warning: undefined slot “label” for component MyAppWeb.CoreComponents.input/1
warning: undefined slot “description” for component MyAppWeb.CoreComponents.input/1

Is there a way to define an attr so it both takes a slot or an ordinary attr?

I’d just make the label be a slot generally. It can take a plain string just fine, but you’re able to validate things properly and you’re not working against the system. I can see the convenience of having an “input” be a slot or attr, but in practise there’s likely a lot of edge cases if that would be supported.

2 Likes

Hmm… this would mean a lot of changes in the (autogenerated) code, and honestly I’m not sure if I like the look of this:

<.input
  field={@form[:email]}
  type="email"
  required
>
  <label>Email</label>
</.input>

vs

<.input
  field={@form[:email]}
  type="email"
  label="Email"
  required
/>

Ok, took the bite and updated ALL my views, but now it’s working and no errors anymore. And the benefit is, that I can use arbitrary HTML now as my label! Thx a lot!