dstockdale

dstockdale

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?

Showing Posts 1 to 4

Hermanverschooten

Hermanverschooten

Not an answer to your question, but aren’t you reinventing the wheel?
CSS was made for what you want to do.
Moreover I feel most people treat the CoreComponents as a gospel to follow, while I think it was more meant to be example code.
You should adapt this to your needs, or even throw it away and make something else if it doesn’t suit your needs.

Going back to your question, you could probably create a new sigil that would allow you to precompile your version to heex.

Sebb

Sebb

You can do that already with descedant and sibling selectors.
Tailwind can partially do it since 3.4, see Tailwind CSS v3.4: Dynamic viewport units, :has() support, balanced headlines, subgrid, and more - Tailwind CSS

But I think having control over the components instead of using a black-box component lib is what will be default in the future.

This is what LV wants you to do with core-components.

Or what you get with things like https://ui.shadcn.com/.

al2o3cr

al2o3cr

FWIW, the design decisions section of the Doggo docs suggests they’d prefer you style div[role=toolbar] button instead of injecting classes all over the DOM.

eahanson

eahanson

+1

Because I like to be in complete control of the app that I’m going to have to maintain for (hopefully) years, the first thing I do in a new Phoenix app is comment out CoreComponents. When I need a component that it provides, I copy just that component into a module that I created (for example, I’ll typically have a Table module with a bunch of table-related components) and then make whatever changes are needed for my particular use case.

(One of the changes that I make is to replace Tailwind with CSS. I mention this here because I see a lot of people use Tailwind thinking that it’s the new widely accepted default and I want everyone to know that some people intentionally avoid Tailwind.)

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews