-
Notifications
You must be signed in to change notification settings - Fork 16
Description
This might be more of a component architecture issue, but I thought I'd throw it out there.
Let's say we have the following Nice Partial for a card component:
<%# app/views/components/_card.html.erb %>
<% yield p = np %>
<%= content_tag :article, class: 'card rounded-lg' do %>
<h2 class="font-lg font-bold"><%= p.yield :heading %></h2>
<%= p.yield :blurb %>
<% end %>… and we render some blog posts using that component:
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<%= render 'components/card' do |p| %>
<% p.content_for :heading, post.title %>
<% p.content_for :blurb, post.description %>
<% end %>
<% end %>Now, say we want to customize the card style these posts, by reducing the roundness of the corners and adding a card--post modifier. (We'll use both utility and BEM-style class names to demonstrate a couple of approaches.) Our desired output would be:
<article class="card card--post rounded-sm">
<h2 class="font-lg font-bold">Hello, world!</h2>
Lorem ipsum
</article>This is quite tricky since, we need to:
- add
card--postwithout clobbering the default class (card) - replace
rounded-lgwithrounded-sm
To satisfy 1., a nice API might look as follows:
<%# app/views/components/_card.html.erb %>
<% yield p = np %>
<%= content_tag :article, class: ['card', 'rounded-lg', local_assigns[:class]] do %>
<h2 class="font-lg font-bold"><%= p.yield :heading %></h2>
<%= p.yield :blurb %>
<% end %><%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<%= render 'components/card', class: 'card--post' do |p| %>
<% p.content_for :heading, post.title %>
<% p.content_for :blurb, post.description %>
<% end %>
<% end %>But how to we override or remove the rounded-lg class? One approach might be to remove the rounded-lg class from the partial, but this would require an adding rounded- classes to every instance.
Or if we're using Tailwind JIT, we could utilise the !important modifier:
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<%= render 'components/card', class: 'card--post !rounded-sm' do |p| %>
<% p.content_for :heading, post.title %>
<% p.content_for :blurb, post.description %>
<% end %>
<% end %>… but I'm wondering if there's a possible built-in solution? For example, could we implement something which mimics the DOMTokenList API:
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<%= render 'components/card', class: 'card--post' do |p| %>
<% p.class_list.replace('rounded-lg', 'rounded-sm') %>
<% p.content_for :heading, post.title %>
<% p.content_for :blurb, post.description %>
<% end %>
<% end %>I'm also wondering if this could somehow apply to options_for, e.g.:
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<%= render 'components/card', class: 'card--post' do |p| %>
<% p.class_list.replace('rounded-lg', 'rounded-sm') %>
<% p.content_for :heading, post.title %>
<% p.options_for(:heading)[:class].remove('font-bold') %>
<% p.content_for :blurb, post.description %>
<% end %>
<% end %>(It's been a while since I looked at #9, so this might not be possible to get this working at all!)