Chevron left

Forms

Input Groups

Theme

Themes/hound/logo.svg

Hound

Framework

Tailwind CSS logo

Tailwind CSS

Forms • Input Groups

Input with label

<div class="form-group">
  <label for="email" class="form-label">Email</label>
  <input type="email" class="form-input" placeholder="john.doe@example.com" aria-label="Email">
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :email, class: "form-label" %>
    <%= f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email" %>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :email, class: "form-label"
    = f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email"

Forms • Input Groups

Input with label and help text

This text helps you, right?

<div class="form-group">
  <label for="email" class="form-label">Email</label>
  <input type="email" class="form-input" placeholder="john.doe@example.com" aria-label="Email">
  <p class="text-sm text-slate-600 dark:text-slate-400 leading-relaxed mt-1">This text helps you, right?</p>
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :email, class: "form-label" %>
    <%= f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email" %>
    <p class="text-sm text-slate-600 dark:text-slate-400 leading-relaxed mt-1">This text helps you, right?</p>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :email, class: "form-label"
    = f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email"
    %p.text-sm.text-slate-600.dark:text-slate-400.leading-relaxed.mt-1 This text helps you, right?

Forms • Input Groups

Input with dynamic error messages

JavaScript or Turbo required.

Add the class .form-input-error dynamically to display an invalid state. The icon and helper text is hidden by default but is displayed when the class gets appended.

Read the Icon documentation for the icon view helper as shown in the following snippet(s).

<div class="form-group relative">
  <input type="email" class="form-input form-input-error pr-10" placeholder="john.doe@example.com" aria-label="Email">
  <%= icon "exclamation-circle", classes: "hidden w-5 h-5 stroke-current text-red-600 dark:text-red-400 absolute right-3 top-3" %>
  <p class="hidden mt-1 text-sm text-red-700 dark:text-red-400">Please enter a valid email</p>
</div>
<!-- ActionView::Helpers::FormTagHelper -->
<div class="form-group relative">
  <%= email_field_tag "email", nil, class: "form-input form-input-error pr-10", placeholder: "Email", "aria-label": "Email" %>
  <%= icon "exclamation-circle", classes: "hidden w-5 h-5 stroke-current text-red-600 dark:text-red-400 absolute right-3 top-3" %>
  <p class="hidden mt-1 text-sm text-red-700 dark:text-red-400">Please enter a valid email</p>
</div>

<!-- ActionView::Helpers::FormHelper -->
<%= form_with model: @form do |f| %>
  <div class="form-group relative">
    <%= f.email_field :email, class: "form-input form-input-error pr-10", placeholder: "Email", "aria-label": "Email" %>
    <%= icon "exclamation-circle", classes: "hidden w-5 h-5 stroke-current text-red-600 dark:text-red-400 absolute right-3 top-3" %>
  </div>
  <%= f.submit class: "btn btn-primary" %>
<% end %>
/ ActionView::Helpers::FormTagHelper
.form-group.relative
  = email_field_tag "email", nil, class: "form-control", "aria-label": "Email", placeholder: "john.doe@example.com"
  = icon "exclamation-circle", classes: "hidden w-5 h-5 stroke-current text-slate-400 absolute left-3 top-3"
  %p.hidden.mt-1.text-sm.text-red-700.dark:text-red-400 Please enter a valid email

/ ActionView::Helpers::FormHelper
= form_with model: @form do |f|
  .form-group.relative
    = f.email_field :email, class: "form-control", "aria-label": "Email", placeholder: "john.doe@example.com"
    = icon "exclamation-circle", classes: "hidden w-5 h-5 stroke-current text-slate-400 absolute left-3 top-3"
  = f.submit class: "btn btn-primary"

Forms • Input Groups

Input with browser-based error messages

Most modern browsers have invalid properties and states you can customize the design for. This type of validation uses those in lieu of reaching for JavaScript.

<div class="form-group">
  <label for="email" class="form-label">Email</label>
  <div class="relative">
    <input type="email" class="form-input peer pr-10 invalid:border-red-700 invalid:text-red-700 invalid:ring-red-50 dark:invalid:border-red-400 dark:invalid:text-red-400 dark:invalid:ring-red-50/10" placeholder="john.doe@example.com" aria-label="Email" value="john.doe@">

    <%= icon "exclamation-circle", classes: "w-5 h-5 stroke-current text-red-700 dark:text-red-400 absolute right-3 top-3 invisible peer-invalid:visible" %>
    <p class="mt-1 text-sm text-red-700 dark:text-red-400 invisible peer-invalid:visible">Please enter a valid email</p>
  </div>
</div>
<!-- ActionView::Helpers::FormTagHelper -->
<div class="form-group">
  <%= label_tag "email", "Email", class: "form-label" %>
  <div class="relative">
    <%= email_field_tag "email", "john.doe@", class: "form-input peer pr-10 invalid:border-red-700 invalid:text-red-700 invalid:ring-red-50 dark:invalid:border-red-400 dark:invalid:text-red-400 dark:invalid:ring-red-50/10", placeholder: "john.doe@example.com", "aria-label": "Email" %>

    <%= icon "exclamation-circle", classes: "w-5 h-5 stroke-current text-red-700 dark:text-red-400 absolute right-3 top-3 invisible peer-invalid:visible" %>
    <p class="mt-1 text-sm text-red-700 dark:text-red-400 invisible peer-invalid:visible">Please enter a valid email</p>
  </div>
</div>

<!-- ActionView::Helpers::FormHelper -->
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :email, class: "form-label" %>
    <div class="relative">
      <%= f.email_field :email, class: "form-input peer pr-10 invalid:border-red-700 invalid:text-red-700 invalid:ring-red-50 dark:invalid:border-red-400 dark:invalid:text-red-400 dark:invalid:ring-red-50/10", placeholder: "john.doe@example.com", "aria-label": "Email" %>
      <%= icon "exclamation-circle", classes: "w-5 h-5 stroke-current text-red-700 dark:text-red-400 absolute right-3 top-3 invisible peer-invalid:visible" %>
      <p class="mt-1 text-sm text-red-700 dark:text-red-400 invisible peer-invalid:visible">Please enter a valid email</p>
    </div>
  </div>
  <%= f.submit class: "btn btn-primary" %>
<% end %>
/ ActionView::Helpers::FormTagHelper
.form-group
  = label_tag "email", "Email", class: "form-label"
  .relative
    = email_field_tag "email", "john.doe@", class: "form-input peer pr-10 invalid:border-red-700 invalid:text-red-700 invalid:ring-red-50 dark:invalid:border-red-400 dark:invalid:text-red-400 dark:invalid:ring-red-50/10", "aria-label": "Email", placeholder: "john.doe@example.com"
    = icon "exclamation-circle", classes: "w-5 h-5 stroke-current text-red-700 dark:text-red-400 absolute right-3 top-3 invisible peer-invalid:visible"
    %p.mt-1.text-sm.text-red-700.dark:text-red-400.invisible.peer-invalid:visible
      Please enter a valid email

/ ActionView::Helpers::FormHelper
= form_with model: @form do |f|
  .form-group
    .relative
      = f.email_field :email, class: "form-input peer pr-10 invalid:border-red-700 invalid:text-red-700 invalid:ring-red-50 dark:invalid:border-red-400 dark:invalid:text-red-400 dark:invalid:ring-red-50/10", "aria-label": "Email", placeholder: "john.doe@example.com"
      = icon "exclamation-circle", classes: "w-5 h-5 stroke-current text-red-700 dark:text-red-400 absolute right-3 top-3 invisible peer-invalid:visible"
      %p.mt-1.text-sm.text-red-700.dark:text-red-400.invisible.peer-invalid:visible
        Please enter a valid email
  = f.submit class: "btn btn-primary"

Forms • Input Groups

Disabled input with label

Adding a disabled attribute to the input field will automatically style disabled inputs

<div class="form-group">
  <label for="email" class="form-label">Email</label>
  <input type="email" class="form-input" placeholder="john.doe@example.com" aria-label="Email" disabled>
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :email, class: "form-label" %>
    <%= f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email", disabled: true %>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :email, class: "form-label"
    = f.email_field :email, class: "form-input", placeholder:  "john.doe@example.com", "aria-label": "Email", disabled: true

Forms • Input Groups

Input with add-on

Using custom offsets you can add an add-on to the beginning or end of an input. Modify the w-[40px] class of the add-on to account for its content. Do the same for the input padding pl-[90px] to adjust offset proportionally.

https://
<div class="form-group">
  <label for="website" class="form-label">Website</label>
  <div class="relative">
    <div class="absolute left-px border-r border-slate-300 top-px bg-slate-100 dark:bg-slate-700/80 dark:border-slate-700 dark:text-slate-200 h-[40px] text-base rounded-l flex items-center justify-center px-3 text-slate-700 select-none">https://</div>
    <input type="text" id="website" class="form-input pl-[90px]" placeholder="example.com" aria-label="Website">
  </div>
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :website, class: "form-label" %>
    <div class="relative">
      <div class="absolute left-px border-r border-slate-300 top-px bg-slate-100 dark:bg-slate-700/80 dark:border-slate-700 dark:text-slate-200 h-[40px] text-base rounded-l flex items-center justify-center px-3 text-slate-700 select-none">https://</div>
      <%= f.text_field :website, class: "form-input pl-[90px]" placeholder: "example.com" "aria-label":"Website" %>
    </div>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :website, class: "form-label"
    .relative
      .absolute.left-px.border-r.border-slate-300.top-px.bg-slate-100.dark:border-slate-700.dark:text-slate-200.text-base.rounded-l.flex.items-center.justify-center.px-3.text-slate-700.select-none{class: "dark:bg-slate-700/80 h-[40px]"} https://
      = f.text_field :website, class: "form-input pl-[90px]" placeholder: "example.com" "aria-label":"Website"

Forms • Input Groups

Input with leading inline and trailing add-ons

$ USD
<div class="form-group">
  <label for="amount" class="form-label">Enter amount</label>
  <div class="relative">
    <span class="absolute left-3 top-[9px] text-slate-500 dark:text-slate-400">$</span>
    <input type="text" id="amount" class="form-input pl-7" placeholder="5.00" aria-label="Enter amount">
    <span class="absolute right-3 top-[11px] text-slate-500 dark:text-slate-400 text-sm">USD</span>
  </div>
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :amount, "Enter amount", class: "form-label" %>
    <div class="relative">
      <span class="absolute left-3 top-[9px] text-slate-500 dark:text-slate-400">$</span>
      <%= f.text_field :amount, class: "form-input pl-7", placeholder: "5.00", "aria-label": "Enter amount" %>
      <span class="absolute right-3 top-[11px] text-slate-500 dark:text-slate-400 text-sm">USD</span>
    </div>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :amount, "Enter amount", class: "form-label"
    .relative
      %span.absolute.left-3.text-slate-500.dark:text-slate-400{class: "top-[9px]"} $
      = f.text_field :amount, class: "form-input pl-7", placeholder: "5.00", "aria-label": "Enter amount"
      %span.absolute.right-3.top-[11px].text-slate-500.text-sm USD

Forms • Input Groups

Input with leading icon and trailing button

<div class="form-group">
  <label for="users" class="form-label">Search users</label>
  <div class="relative">
    <%= icon "users", classes: "w-5 h-5 stroke-current text-slate-500 absolute left-3 top-3" %>
    <input type="search" id="users" class="form-input pl-10" placeholder="John Doe" aria-label="Search users" />
    <button class="rounded-r rounded-l-none bg-slate-100 border-slate-300 border rounded px-4 py-2 absolute right-0 shadow-sm top-0 focus:ring-4 focus:ring-indigo-50 focus:border-slate-400 text-slate-700 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600">Search</button>
  </div>
</div>
<%= form_with model: @form do |f| %>
  <div class="form-group">
    <%= f.label :users, "Search users", class: "form-label" %>
    <div class="relative">
      <%= icon "users", classes: "w-5 h-5 stroke-current text-slate-500 absolute left-3 top-3" %>
      <%= f.search_field :users, class: "form-input pl-10", placeholder: "John Doe", "aria-label": "Search users" %>
      <%= f.submit class: "rounded-r rounded-l-none bg-slate-100 border-slate-300 border rounded px-4 py-2 absolute right-0 shadow-sm top-0 focus:ring-4 focus:ring-indigo-50 focus:border-slate-400 text-slate-700 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600" %>
    </div>
  </div>
<% end %>
= form_with model: @form do |f|
  .form-group
    = f.label :users, "Search users", class: "form-label"
    .relative
      = icon "users", classes: "w-5 h-5 stroke-current text-slate-500 absolute left-3 top-3"
      = f.search_field :users, class: "form-input pl-10", placeholder: "John Doe", "aria-label": "Search users"
      = f.submit class: "rounded-r rounded-l-none bg-slate-100 border-slate-300 border rounded px-4 py-2 absolute right-0 shadow-sm top-0 focus:ring-4 focus:ring-indigo-50 focus:border-slate-400 text-slate-700 dark:bg-slate-700 dark:text-slate-100 dark:border-slate-600"