Why no Rails Components?
If there are two things you should know about me as a developer it's that I love Ruby on Rails and that I value speed above all else when it comes to building. I've been using Ruby on Rails so well over a decade and one of the reasons I love it so much is because it aligns with my second value of speed. Ruby on Rails is one of the fastest frameworks I've seen to getting web applications up and running while creating a sound architecture for expansion.
I could write a lot about how it does that and put the framework into the context of other frameworks today, but that's not the point of this post. The point of this post is to talk about an area where Ruby on Rails is woefully behind and more to the point, slow.
The Problem: The Frontend
Since the beginning, Rails treated the frontend as a second class citizen. It was always assumed that you would use Rails to render HTML and that was it. If you wanted to do anything more than that, you were on your own. This was fine for a while, but as the web has evolved, this has become a bigger and bigger problem. Where React shines is that it is all frontend. Now obviously, that comes at the expense of so much, but with React, you can really get a stylish and super interactive frontend pretty quick.
The main manner in which React provides developers with this speed is through shareable components that you can just drop into your application and they work. Like look at this shiny piece of frontend beauty magic.
import { Drawer } from 'vaul';
function MyComponent() {
return (
<Drawer.Root>
<Drawer.Trigger>Open</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Content>
<p>Content</p>
</Drawer.Content>
<Drawer.Overlay />
</Drawer.Portal>
</Drawer.Root>
);
}
I mean that's pretty cool. I don't know of a mechanism in Rails with which to achieve something like that.
Current Solutions
There are some ways you could get that sort of interoperability and composability of components. One, there are plenty of Javascript libraries that provide the base functionality of such interactions. I can't at the moment find one for that sort of mobile drawer effect, but I'm sure they exist.
These libraries generally provide your application with a javascript object to be initialized and bound to your DOM. So to implement them, you have to put the library in the context of a view, generally include or write markup for the HTML of the component you want to use, perhaps copy and pasting from the library example. You then need to put the javascript library into the context of a stimulus controller and initialize it and bind it correctly. Oh and you also have to account for the styles.
It's possible and it works, its just a good amount of work and each step introduces friction points and breaking potential.
Another more modern concept might be actually using web components. I haven't tried this but you could use libraries like Shoelace. Certainly web components seems to check a lot of the boxes of drop-in interoperable fully encapsulated components.
The thing about those is I have no experience with them, they are pretty modern and I'm not sure what the adoption of them from a developer perspective is like, they certainly require adding a layer of abstraction to your Rails application, it's not as bad as, but it's sort of like saying "if you want this functionality, just use React with your Rails application."
I think there has to be a better way.
What I Want
Looking at that awesome Vaul drawer example, or looking at full component libraries and themes such as the incredibly well designed and popular shadcn, what I want in Rails is something like:
<%= render_drawer do %>
<%= drawer_trigger "Open" %>
<%= drawer_content do %>
<p>Content</p>
<% end %>
<% end %>
I want that code in my rails views to take care of everything, the underlying markup required, literally the structure of the HTML to create the component and interaction, the styling of the that markup so it looks awesome, and then the javascript, in the form of a stimulus controller bound to the markup, that provides the functionality. I want all of that, I want to think about none of it, and I want to easily be able to customize all parts of it in the future. Is that really so much to ask?
Oh, and also, I want no new dependencies, libraries, or indirections. That is to say, I want all of this accomplished staying as close to vanilla Rails as possible.
The Solution: Rails Components
I'm building Rails Components to solve this problem. I want to be able to drop in components into my Rails applications and have them just work. I want to be able to customize them and I want to be able to do it all without having to think about the underlying HTML, CSS, or Javascript. I want to be able to do it all in Rails. And not only is this possible, I've already shown it to be by porting the majority of shadcn to rails.
In the next few days I'm going to write about why this is important to me, how I'm accomplishing this, and where I'm going with it. So stay tuned, should be a fun week of posts!
I'd would really love your feedback and thoughts on all of this so please, leave a comment or ask a question. And especially if you're already using shadcn on rails, I'd love to hear from you.
Top comments (0)