-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modifying HTML attributes within a Nice Partial #13
Comments
The above was a brain dump whilst recovering from my 2nd Covid jab 🥴, so to hopefully provide a bit more clarity… Given a basic card component partial, let's say we want to render a list of blog posts as cards, but we wish to customise the HTML a little. Our caller template might look like: <%= render 'components/card', class: 'post', tag: :article do |s| %>
<% s.options_for :header, class: 'post__header' %>
<% s.content_for :heading, post.title, tag: :h2 %>
<% s.content_for :body, post.excerpt, class: 'post__body' %>
<% end %> This should render: <article class="card post">
<header class="card__header post__header">
<h2>…</h2>
</header>
<div class="card__body post__body">
…
</div>
</article> The criteria:
Questions
I'm finding it a bit difficult to get my head around what's best here. I like the aesthetics of the first code example, but would appreciate some feedback. I'm totally getting ahead of myself, but if we go ahead with merging values, we could move towards something like the following: <% # Set up the default options _before_ `yield p` for consumption in the caller template
p = np(class: 'card')
p.options_for :header, class: 'card__header'
p.options_for :body, class: 'card__body'
p.helpers do
def heading_tag
@heading_tag ||= (options_for(:heading).delete(:tag) || :h1)
end
end
yield p
%>
<%= content_tag local_assigns.delete(:tag) || :div, options do %>
<%= content_tag :header, p.options_for :header do %>
<%= content_tag heading_tag, p.content_for(:heading) %>
<% end %>
<%= content_tag :div, p.content_for(:body), p.options_for(:body) %>
<% end %> It's not ideal that the options have to be set at the top, away from the actual elements, but I'm not sure there's a way round this if we want them to be accessible from the caller template. Also there's a lot of Finally, to add a bit more sugar, we could simplify the following emerging pattern: <%= content_tag :div, p.content_for(:body), p.options_for(:body) %> …to: <%= p.slot_tag_for :div, :body %> |
rails/rails#42682 has shipped and will be part of Rails 7. It might be useful if rails/rails#41638 had originally explored built-in support for (deep-)merging values into It felt a little half baked, so it was closed. In its place, I created https://github.com/seanpdoyle/action_view-attributes_and_token_lists to further explore the possibilities. It feels like it'd be a great fit for NicePartials! |
@seanpdoyle Really appreciate this! Will take a look soon! |
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:
… and we render some blog posts using that component:
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:This is quite tricky since, we need to:
card--post
without clobbering the default class (card
)rounded-lg
withrounded-sm
To satisfy 1., a nice API might look as follows:
But how to we override or remove the
rounded-lg
class? One approach might be to remove therounded-lg
class from the partial, but this would require an addingrounded-
classes to every instance.Or if we're using Tailwind JIT, we could utilise the
!important
modifier:… but I'm wondering if there's a possible built-in solution? For example, could we implement something which mimics the DOMTokenList API:
I'm also wondering if this could somehow apply to
options_for
, e.g.:(It's been a while since I looked at #9, so this might not be possible to get this working at all!)
The text was updated successfully, but these errors were encountered: