In my project we have a Text
component that respects the design system implementation with different sizes and line-heights. Then our typography has these variations:
- h1…h5
- base
- large
- medium
- small
for base
, medium
and small
variations we can use <span />
or <p/>
tag. However, for h1..h5
variations it would be better to respect HTML semantics using those exact tags.
So I thought: I can pattern match on the prop size
of the text
component and then render something based on it. Or use flow control in heex
tempaltes, that way:
attr :size, :string, values: ~w(h1 h2 h3 h4 h5 base lg md sm), required: true
def text(assigns) do
~H"""
<h1 :if={@size == "h1"}> ... </h1>
<h2 :if={@size == "h2"}> ... </h2>
<h3 :if={@size == "h3"}> ... </h3>
<!-- go for each variation -->
"""
end
But this code is kinda long… So I tried to render dynamically:
defp text_component(variation) do
case variation do
"h1" -> ...
end
end
def text(assigns) do
~H"""
<!-- what goes here? I want to call text_component(@size) and get a HTML tag rendered -->
"""
end
I know I can render function components dynamically with apply/3
or even with Phoenix.LiveView.HTMLEngine.component/3
, but how about native HTML tags? I would need to define a micro component to render the tag? maybe:
def h1(assigns) do
~H"<h1 {...@assigns}> ... </h1>"
end