Just pondering here but is there some conceivable way to one day separate the core markup of components and what styles them?
I know that’s currently not possible, but I’m just wondering if it could be viable.
Here’s an example of what I mean. I don’t love the classes that core_components.ex
comes with and sure I can go through and customize this file to hearts content but I’d sort of prefer to do things in a different and perhaps more reusable way.
e.g.
def simple_form(assigns) do
~H"""
<.form :let={f} for={@for} as={@as} {@rest}>
<div class="mt-10 space-y-8 bg-white">
<%= render_slot(@inner_block, f) %>
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
<%= render_slot(action, f) %>
</div>
</div>
</.form>
"""
end
So I can pass a class="special-class"
to my <.simple_form
tag but it still comes with 2 places that have static classes that I might not like.
What I’d love to somehow be able to do is something akin to stylesheets but also not exactly. I had a weird idea that it might be possible to merge heex markup together so one part could be completely unstyled or ‘headless’ as it’s sometimes referred to.
For instance I like Doggo’s style. It’a great collection of useful headless components that focus of accessibility. That’s great, but I’d still like to have a way of making them my own beyond just passing class attributes or copying and editing the components.
e.g. from Doggo
def action_bar(assigns) do
~H"""
<div role="toolbar" class={["action-bar" | List.wrap(@class)]} {@rest}>
<button :for={item <- @item} phx-click={item.on_click} title={item.label}>
<%= render_slot(item) %>
</button>
</div>
"""
end
Here I can add a class for the wrapping div but I can’t directly access the button within.
./core_components.ex
defmodule ExampleWeb.CoreComponents do
# My imaginary macro for applying styles
use ComponentStyling, :default_styles
# Pinching Doggo's action_bar as a simple example
def action_bar(assigns) do
~H"""
<div role="toolbar">
<button :for={item <- @item} phx-click={item.on_click} title={item.label}>
<%= render_slot(item) %>
</button>
</div>
"""
end
./default_styles.ex
defmodule ExampleWeb.DefaultStyles do
...
# Matching function contains `<style:elem` tags applying applying
# things like classes to the heex template
def action_bar(assigns) do
~H"""
<style:div class="nav-default">
<syle:button class="bg-blue-500 hover:bg-pink-500 etc" />
</style:div>
"""
end
I’m just making stuff up here to get a point across and many might think it’s a terrible idea but I think it would make working with heex templates quite interesting. Libraries like Doggo could evolve and ship with default styles that people could every easily style themselves.
Of course styling with <style:div
could be very laborious (it’s just an idea iac) but I’d imagine doing a generator would make sense mix phx.styles custom_components custom_style
. This would read your heex templates from custom_components.ex and export matching <style:etc
ones
After this long imaginative discourse on what I was thinking about my actual question is is there a way or how would you approach being able to merge heex templates or is that just a terrible idea?