Hey, everyone.
I’ve been working with Phoenix Components for a few weeks, and they are great. One thing I use a lot when building custom components is the global attribute with default values set. It’s a good option for building reusable elements without repeating stuff every time.
However, I’ve noticed a “pattern” when creating components with class modifiers.
Suppose I have a <.paragraph />
:
attr :rest, :global, default: %{class: "paragraph"}
slot :inner_block, required: true
def paragraph(assigns) do
~H"""
<p {@rest}><%= render_slot(@inner_block) %></p>
"""
end
<.paragraph>My paragraph</.paragraph>
<p class="paragraph">My paragraph</p>
The problem is that I have modifiers for my paragraph, like paragraph--medium
, paragraph--small
, or even other types of classes like is-hidden
, is-animateable
etc. To use them, I need to repeat its base class.
<.paragraph class="paragraph paragraph--with-modifier">
This is a paragraph with a modifier
</.paragraph>
<p class="paragraph paragraph--with-modifier">My paragraph</p>
Of course, changing how things currently work because I don’t want to repeat a class is not a good idea, and I understand the default
value is not the best option for what I’m trying to do. But things can get more complex as we have more than a single base class.
Also, I don’t think creating additional components to consider all the modifiers they could have is a good idea. It’s just simpler to use classes.
Now, to the suggestion: what if we had something like an initial
property for the class
in global attributes? Values from it would be combined with the values passed to the component automatically.
attr :rest, :global, initial: %{class: "paragraph is-animateable is-i-dont-know"}
slot :inner_block, required: true
def paragraph(assigns) do
~H"""
<p {@rest}><%= render_slot(@inner_block) %></p>
"""
end
<.paragraph class="paragraph--with-modifier">
This is my paragraph with modifiers
</.paragraph>
<p class="paragraph is-animateable is-i-dont-know paragraph--with-modifier">This is my paragraph with modifier</p>
I read this article, which is a great workaround, but maybe we can improve it.
What do you all think?
Thanks!