Simple_form: Some integration support for Tailwindcss?

Created on 16 Jan 2021  Β·  8Comments  Β·  Source: heartcombo/simple_form

Hi guys

I would like to ask if you are considering adding support to Tailwindcss

Thanks

Most helpful comment

https://github.com/abevoelker/simple_form_tailwind_css/blob/2c6e7d3654bc2f5dc1bf43db4618f968ce874502/lib/generators/simple_form/tailwind/templates/simple_form.rb

It’s kinda intertwined with the gem though (namely stuff that depends on
the OverwriteClassWithErrorOrValidClass mixin)

On Sat, May 22, 2021 at 8:26 PM Yordis Prieto @.*>
wrote:

@abevoelker https://github.com/abevoelker would you mind sharing your
configuration file? I would like to use it as the baseline πŸ™πŸ»

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/heartcombo/simple_form/issues/1723#issuecomment-846486567,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AABFO45YNYTQQD2NMY3KCSDTPBKS7ANCNFSM4WEYNVXQ
.

All 8 comments

I don't have experience with Tailwind to build anything out of the box, it's not something that's on my radar for the near term at least, but perhaps in the future.

I do think that the wrapper support in SF should be mostly enough to build a set of default configs for your own needs, and I'd be happy to support adding anything that might be missing, but I'm not sure about maintaining such configs with SF itself for now. If you (or someone else coming here) have a set of configs, maybe a starting point would be the wiki.

FWIW, Bootstrap support was added really long ago and is now mainly maintained via https://github.com/rafaelfranca/simple_form-bootstrap, and there hasn't been any changes for the past couple of years.

As mentioned in #1727, I made an attempt at adding a Tailwind component using the Wrappers API:

config.wrappers :tailwind_text_input, tag: 'div', class: '', error_class: '', valid_class: '' do |b|
  b.use :html5
  b.use :placeholder
  b.optional :maxlength
  b.optional :minlength
  b.optional :pattern
  b.optional :min_max
  b.optional :readonly

  b.use :label, class: "block text-sm font-medium text-gray-700"
  b.wrapper tag: 'div', class: 'mt-1', error_class: 'relative rounded-md shadow-sm' do |c|
    c.use :input,
      class: 'appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm',
      error_class: 'block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md'
    c.use :full_error, wrap_with: { tag: 'p', class: 'mt-2 text-sm text-red-600' }
  end
end

Which I use like this:

<%= f.input :email, wrapper: :tailwind_text_input, autocomplete: "email", placeholder: "[email protected]", label: "Email address" %>

That wrapper is a first attempt to mimic this HTML:

<%= simple_form_for(@user, url: profiles_path, html: { class: "space-y-6" }) do |f| %>
  <div>
    <%= f.label :email, class: "block text-sm font-medium text-gray-700" do %>
      Email address
    <% end %>
    <%- if f.object.errors[:email].any? -%>
    <%- input_classes = "block w-full pr-10 border-red-300 text-red-900 placeholder-red-300 focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm rounded-md" -%>
    <%- else -%>
    <%- input_classes = "appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" -%>
    <%- end -%>
    <div class="mt-1  <%= 'relative rounded-md shadow-sm' if f.object.errors[:email].any? %>">
      <%= f.text_field :email, autocomplete: "email", required: true, placeholder: "[email protected]", class: input_classes %>
      <%- if f.object.errors[:email].any? -%>
      <div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
        <!-- Heroicon name: solid/exclamation-circle -->
        <svg class="h-5 w-5 text-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
          <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
        </svg>
      </div>
      <% end %>
    </div>
    <%- if f.object.errors[:email].any? -%>
    <p class="mt-2 text-sm text-red-600"><%= f.object.errors.full_messages_for(:email).join(", ") %></p>
    <%- end -%>
  </div>

  <!-- (other fields elided) -->
<% end %>

That HTML should render something like this given a fresh form with a blank model:

wN9Cj

And when there's an error, it will look something like this:

YO6Om

Besides the problem I mentioned in #1727 with the missing 'relative rounded-md shadow-sm' error classes, I had some other difficulties in modeling this component in Simple Form:

  1. I don't see a way to conditionally append the <svg> icon after the <input> when there's an error using the wrappers API. Presumably I'll have to write a custom input to support this?
  2. When it comes to classes, Simple Form seems to have the notion of class, error_class, and valid_class. It seems that the class is always used for the component, and error_class and valid_class are added on as additional classes if the component has errors or is valid, respectively. This doesn't work for my component, because I want my field's colors to be border-gray-300 focus:ring-indigo-500 focus:border-indigo-500 when the model is a new record, but if there's an error it should overwrite those classes with border-red-300 focus:ring-red-500 focus:border-red-500.

    The way it's working right now when there's an error, it adds my error classes on top of the indiglo classes, leading to me seeing indiglo outlines instead of red in Chrome:

    issue

    I can't figure out how to work around this besides either patching Simple Form's default behavior or doing something hacky like this:

    <%- if @user.new_record? -%>
    <%= f.input :email, wrapper: :tailwind_text_input, autocomplete: "email", placeholder: "[email protected]", label: "Email address", input_html: { class: 'appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm' } %>
    <%- else -%>
    <%= f.input :email, wrapper: :tailwind_text_input, autocomplete: "email", placeholder: "[email protected]", label: "Email address", input_html: { class: '' } %>
    <%- end -%>
    

    Is there a better way to handle that which I'm not seeing?

Well, I ended up creating a custom input and custom form builder to get the required behavior. Here's the gem in an early stage if anyone wants to help me add more Tailwind components.

@abevoelker thanks for all the information on tailwind here. Unfortunately like I mentioned above, I don't have much experience with tailwind, I hope to be able to learn that better at some point, but I'm happy to help and see if we can make SimpleForm flexible enough to support it.

I left a comment on #1727 about that not being something we currently support I believe. Regarding your questions:

  1. I don't see a way to conditionally append the icon after the

I believe a custom input would be the way to go here, especially considering this is conditional to the error state.

When it comes to classes, Simple Form seems to have the notion of class, error_class, and valid_class. It seems that the class is always used for the component, and error_class and valid_class are added on as additional classes if the component has errors or is valid, respectively

Correct, the class is always there, the others only build on top, it's meant to be an always present/default class. There's no way to override class once you add it. It sounds like what you'd like is a fallback if no error is present for example, that'd likely be something different/custom to build.


It sounds to me that SF might need even more flexibility to achieve tailwind's requirements. I'll take a look at the gem code, see what I can learn from that as well, thanks for sharing that.

Unfortunately like I mentioned above, I don't have much experience with tailwind, I hope to be able to learn that better at some point, but I'm happy to help and see if we can make SimpleForm flexible enough to support it.

That's understandable, I'm still learning it myself even. Thanks for lending your support to the Simple Form side of things

I believe a custom input would be the way to go here, especially considering this is conditional to the error state.

Yeah you were correct - I ended up getting what I needed working with a custom input

Correct, the class is always there, the others only build on top, it's meant to be an always present/default class. There's no way to override class once you add it. It sounds like what you'd like is a fallback if no error is present for example, that'd likely be something different/custom to build.

Thanks for that - I ended up with a mixin that patches an input's behavior to do what I need which I'll use in my custom inputs.

It sounds to me that SF might need even more flexibility to achieve tailwind's requirements. I'll take a look at the gem code, see what I can learn from that as well, thanks for sharing that.

That would be great! Just one request - I'm just starting to get the hang of writing custom inputs and custom form builders; if you wouldn't mind waiting about one week to give me time to write more components and refactor the code, I think your time would be better spent. :smile:

Sounds good, appreciate it @abevoelker. Feel free to ping back here once you think it's in a good place for further look :). Thanks again.

@abevoelker would you mind sharing your configuration file? I would like to use it as the baseline πŸ™πŸ»

https://github.com/abevoelker/simple_form_tailwind_css/blob/2c6e7d3654bc2f5dc1bf43db4618f968ce874502/lib/generators/simple_form/tailwind/templates/simple_form.rb

It’s kinda intertwined with the gem though (namely stuff that depends on
the OverwriteClassWithErrorOrValidClass mixin)

On Sat, May 22, 2021 at 8:26 PM Yordis Prieto @.*>
wrote:

@abevoelker https://github.com/abevoelker would you mind sharing your
configuration file? I would like to use it as the baseline πŸ™πŸ»

β€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/heartcombo/simple_form/issues/1723#issuecomment-846486567,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AABFO45YNYTQQD2NMY3KCSDTPBKS7ANCNFSM4WEYNVXQ
.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

frankyston picture frankyston  Β·  4Comments

JanStevens picture JanStevens  Β·  5Comments

aximuseng picture aximuseng  Β·  4Comments

mmhan picture mmhan  Β·  4Comments

gregblass picture gregblass  Β·  3Comments