benlime

benlime

I created a new library GitHub - benvp/ex_cva: Class Variance Authority for Elixir · GitHub which aims to make it very easy to define different variations of function components. I experimented and tweeted about it a bit and I really like how the api is looking now.

This library is heavily inspired by the amazing work of Joe Bell on GitHub - joe-bell/cva: Class Variance Authority · GitHub in the JS world. The approach reasonates so much with me, that I wanted to have something similar in the elixir world.

What do you guys think?

Showing Posts 1 to 6

LostKobrakai

LostKobrakai

I just had a quick look at the readme, but wanted to leave a thank you for retaining the simple functional API. Macros are great, but I’d be worried wrapping Phoenix.Component that things will break with future liveview versions, but I can see myself using the plain API.

benlime

benlime OP

I separated the both apis because they are building upon each other. So the core logic is just constructing the proper class names and the declarative api is build upon it to make it a little more convenient.

I understand that something potentially could break on new LiveView versions but I’d argue that the risk is quite low. The macro based approach essentially

  • creates a few module attributes to keep track of the cva related configs/state.
  • generating Phoenix.Component.attr/3 calls with values derived from the variant.
  • wrapping the function component and calling Phoenix.Component.assign/2. This is the same approach which LiveView does internally for declarative components.

I’m not touching LiveView internals and only use public apis.

Scenarios where it could potentially break:

  • Changes in the attr/3 api in a breaking manner.
  • The definition of HEEx function components is changed. Like requiring multiple arguments.

I think that’s both pretty unlikely. And even if it happens, as the cva macros api is very thin layer.

benlime

benlime OP

I just released version 0.1.2 of ex_cva and improved the docs a bit after receiving some feedback.

The version fixes an issue which would always apply class assigns if it was present, even if @class has not been explicitly passed into the component. This could end up in having duplicate classes if a component configures variants and accepts a class assign.

jondelmil

jondelmil

Thanks for the very nice library!

I’m curious how you recommend dealing with variants that arise from the presence of HTML attributes. For instance,

<button intent="secondary" disabled>
  hello
</button>

vs

<button intent="destructive" disabled>
  hello
</button>

should be styled differently.

In my example above, the original CVA lib seems to recommend making disabled another intent variant which I’ve done for now, but do you have advice for composing these more easily?

benlime

benlime OP

Thanks for bringing that up Jon. I found a few things in the library when using that approach.

In general I agree with the way the original CVA library recommends on handling things like disabled. Adding a new boolean variant if the way to go. Otherwise you could also add classes with the :disabled css pseudoclasses to style the button, when it’s disabled.

Starting with 0.2.0 of ex_cva you can do sth like the post recommended. Read below.

benlime

benlime OP

I just release version 0.2.0 of ex_cva.

[v0.2.0] (2022-12-06)

Improvements

  • variant/2 now properly supports boolean values. You can now do something like the following:
variant :disabled,
        [true: "disabled-class", false: "enabled-class"],
        default: false
        
# or

variant :disabled,
        [true: "disabled-class"],
        default: nil
        
def button(assigns) do
  ~H"""
  <button class={@cva_class} disabled={@disabled}>
    <%= render_slot(@inner_block) %>
  </button>
  """
end
        
# ... where you use that component

<.button disabled>Click me</.button> 

# -> <button class="disabled-class" disabled>Click me</button>
— All posts loaded —

Where Next? Top

Trending in Announcing Top

restlessronin
The repo is at GitHub - cyberchitta/openai_ex: Community maintained Elixir library for OpenAI API · GitHub. Docs are at OpenaiEx User Gu...
152 12366 136
New
type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
kip
In 2021 I started a new library called Tempo with the objective of modelling time as a set of intervals - not as instants. In 2022 I gave...
New
quatermain
Hello, I’m sharing my plugin here in forum after some time so it has time to mature and proof yourself. I use Claude Code daily on a pr...
New

Other Trending Topics Top

KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews