Forms

The forms component from Instrumental Components powers up your Rails app's forms by providing consisten form styling and handling various types of form fields.

At it's core is the form-control CSS class, which gives all form fields a consistent look and feel.

The forms component also provides additional styling and funtionality for handling various other form-related things in Rails such as:

  • Styling Rich Text (trix) fields
  • Labels, descriptions, and tooltips
  • Start and/or end caps on fields
  • Color pickers
  • Selection dropdowns
  • and more

Installation

Copy
rails g instrumental:forms

To insert a sample form into a view:

Copy
rails g instrumental:forms:insert

The form field wrapper

To style a form field using Instrumental Components, simply wrap your Rails form field helper in the _field partial, like this:

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "Name",
            name: :name,
            tooltip: "This is a tooltip" do %>
  <%= f.text_field :name,
                    placeholder: "Name",
                    class: form_control_classes %>
<% end %>

Find details on all of the customization options you can apply to a form field by checking out the list of local variables in this file:

app/views/shared/components/forms/_field.html.erb

Rich Text fields

In order to apply Instrumental's styling to Rich Text fields (a.k.a. Trix fields), you'll need to add a few things:

  • Add the rich_text_field: true option to the field wrapper
  • Add the data-controller="components--rich-text" attribute to the field
  • Add the data-action="focus->components--rich-text#focus blur->components--rich-text#unfocus" attribute to the field

Like this:

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "Description",
            name: :description,
            tooltip: "This is a tooltip",
            rich_text_field: true do %>
  <%= f.rich_text_area :description,
                        data: {
                          controller: "components--rich-text",
                          action: "focus->components--rich-text#focus blur->components--rich-text#unfocus"
                        } %>
<% end %>

Checkbox fields

When displaying a single checkbox field, you should add wrap_label: true to the field wrapper. The label appears above the field, by default, but when you add wrap_label: true, the label appears to the right of the field.

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "I agree to the terms and conditions",
            name: :terms_of_service,
            wrap_label: true do %>
  <%= f.check_box :terms_of_service %>
<% end %>

When displaying a group of checkboxes, you can wrap each of those checkbox fields within another field partial, like this:

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "Group label" do %>
  <%= render "shared/components/forms/field",
              form: f,
              label: "I agree to the terms and conditions",
              name: :terms_of_service,
              wrap_label: true do %>
    <%= f.check_box :terms_of_service %>
  <% end %>
  <%= render "shared/components/forms/field",
              form: f,
              label: "I agree to the terms and conditions",
              name: :terms_of_service,
              wrap_label: true do %>
    <%= f.check_box :terms_of_service %>
  <% end %>
  <%= render "shared/components/forms/field",
              form: f,
              label: "I agree to the terms and conditions",
              name: :terms_of_service,
              wrap_label: true do %>
    <%= f.check_box :terms_of_service %>
  <% end %>
<% end %>

Radio button groups

The same concept as multiple checkboxes can be applied to radio button groups:

Wrap your group of radio buttons within another field partial, like this:

Copy
<%= render "shared/components/forms/field",
            label: "Guitar Type",
            description: "This is a description for the guitar type.",
            tooltip: "This is a tooltip" do %>
  <% Guitar.guitar_types.keys.each do |type| %>
    <%%= render "shared/components/forms/field",
                form: f,
                label: type.titleize,
                tooltip: "This is a tooltip for #{type.titleize}",
                name: "guitar_type_#{type}",
                wrap_label: true do %>
      <%= f.radio_button :guitar_type, type %>
    <% end %>
  <% end %>
<% end %>

Selection dropdowns

To style a selection dropdown, add the select_field: true option to the field wrapper, like this:

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "Thing Type",
            name: :thing_type,
            tooltip: "This is a tooltip",
            select_field: true do %>
  <%= f.select :thing_type,
              Thing.thing_types.keys.map { |type| [type.humanize, type] },
              { include_blank: true },
              { class: "form-control" } %>
<% end %>

Color pickers

Instrumental provides a color picker component, which lets users select a color from a color picker or type in a hex code.

Implement the color picker field by adding:

  • The color_field: true option to the field wrapper
  • The data-controller="components--color-picker" attribute to the field

Like this:

Copy
<%= render "shared/components/forms/field",
            form: f,
            label: "Color",
            name: :color,
            placeholder: "Color",
            color_field: true do %>
  <%= f.color_field :color,
                    data: {
                      "components--color-picker-target": "colorPicker"
                    } %>
<% end %>

Image upload fields

Instrumental provides an image upload field, which will display the currently saved image and provide a link to delete the image or replace it. It also has special styling to improve the upload button.

First, you can add the image upload field using this code:

Copy
<%= render "shared/components/forms/field",
            image_upload_field: true,
            form: f,
            label: "Image",
            name: :image,
            tooltip: "This is a tooltip",
            image_object: @guitar.image,
            delete_image_path: remove_guitar_image_path(@guitar) do %>
  <%= f.file_field :image,
                    accept: 'image/*',
                    data: {
                      "components--image-upload-target": "input",
                      action: "components--image-upload#updateImage components--image-upload#revealImagePreview"
                    } %>
<% end %>

You should also set up a controller action to handle the deletion of the image. That action should look something like this:

Copy
<% def remove_guitar_image
  @guitar.image.purge
  redirect_to edit_guitar_path(@guitar), notice: "Image removed successfully."
end %>

Avatar image upload fields

Avatar image upload fields are a slight variation on the image upload field. They show a preview of the avatar image and display a circular version of the current avatar image.

Copy
<%= render "shared/components/forms/field",
            image_upload_field: true,
            avatar_field: true,
            avatar_resource: current_user,
            form: f,
            label: "Avatar",
            name: :avatar,
            tooltip: "This is a tooltip",
            delete_image_path: remove_user_avatar_path do %>
  <%= f.file_field :avatar,
                    accept: 'image/*',
                    data: {
                      "components--image-upload-target": "input",
                      action: "components--image-upload#updateImage components--image-upload#revealImagePreview"
                    } %>
<% end %>
Instrumental Components

I created Instrumental Components to make designing and building professional apps with Ruby on Rails easy, fast, and fun. I use it on all of my projects and I hope it helps you build something great.

Brian Casel
Brian Casel
Creator of Instrumental Components
Learn more Send me a question or request