Input

An input captures data from the user; a wide variety of types are available. The input is one of the most powerful components due to the number of combinations of input types and variations.

Honeycomb allows extensive customization for form inputs.

The most basic HTML structure is as follows:

<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="first-name-0">
      Name
    </label>
    <div class="flix-input__container">
      <input type="text" id="first-name-0" class="flix-input__field"/>
    </div>
  </div>
</div>

You can visually hide the input labels using the flix-sr-only helper to maintain proper accessible names for the input fields:

<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label flix-sr-only" for="last-name-0">
      Family name
    </label>
    <div class="flix-input__container">
      <input type="text" id="last-name-0" class="flix-input__field" placeholder="Name"/>
    </div>
  </div>
</div>

Disabled state

To disable a form input you should add the --disabled modifier to the component wrapper and the disabled attribute to the input element:

<div class="flix-form-row">
  <div class="flix-input flix-input--disabled">
    <label class="flix-label flix-input__label" for="first-name-1">
      Name
    </label>
    <div class="flix-input__container">
      <input type="text" id="first-name-1" class="flix-input__field" placeholder="Can&#x27;t touch this" disabled=""/>
    </div>
  </div>
</div>

Input types

We aim to provide the Honeycomb look and feel for all browser native functionalities. This includes the native input type decorations such as time and date icons. We do not enforce any rules (only visuals), but these input types can accept some handy attributes that you can use for validation or formatting.

Using correct input types is very helpful for user experience, specially on mobile phones with touch keyboards. So we highly encourage you to check this native input documentation of types, attributes and more for up to date definitions of what is possible to do and browser support.

If you happen to find any native decoration that is not yet covered on Honeycomb, please submit a Honeycomb request so we can add it on one of our next releases.

<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="time-example">
      Time
    </label>
    <div class="flix-input__container">
      <input type="time" id="time-example" min="09:00" max="18:00" list="available-times" class="flix-input__field" value="10:00"/>
    </div>
    <datalist id="available-times">
      <option value="09:00">09:00</option>
      <option value="10:00">10:00</option>
      <option value="13:00">13:00</option>
      <option value="14:00">14:00</option>
      <option value="17:00">17:00</option>
      <option value="18:00">18:00</option>
    </datalist>
  </div>
</div>
<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="date-example">
      Date
    </label>
    <div class="flix-input__container">
      <input type="date" id="date-example" class="flix-input__field" value="1996-02-27"/>
    </div>
  </div>
</div>

With icons

You can add icons to the sides of the input, such as the magnifier icon for a search input or a clear button.

Simply add an icon component and give them the flix-input__icon class name in addition to the icon ones.

<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="origin-0">Origin</label>
    <div class="flix-input__container">
      <i class="flix-input__icon flix-icon flix-icon-pin" aria-hidden="true"></i>
      <input type="text" id="origin-0" class="flix-input__field" value="Pallet Town"/>
    </div>
  </div>
</div>

You can change the icon position by moving the icon relative to the field in the document.

You can also use a button as the icon element, if you do so you have to give it an accessible label (aria-label) that explains the button's functionality.

When you have an icon to the right of the input you must use the --has-icon-right modifier in order to adjust the right paddings of the input field.

<form class="flix-form-row">
  <div class="flix-input flix-input--has-icon-right">
    <label class="flix-label flix-input__label" for="destination-0">Destination</label>
    <div class="flix-input__container">
      <i class="flix-input__icon flix-icon flix-icon-pin" aria-hidden="true"></i>
      <input type="text" id="destination-0" class="flix-input__field" value="Viridian City"/>
      <button type="reset" aria-label="Clear locations." class="flix-input__icon flix-btn flix-btn--link flix-btn--square flix-btn--sm">
        <i class="flix-btn__icon flix-icon flix-icon-close" aria-hidden="true"></i>
      </button>
    </div>
  </div>
</form>

With controls

The controls area supports exactly 2 buttons and is typically used to hold input controls like arrows to increase and decrease the input value.

The most common example is the date picker for the search mask, where the user can navigate through days using the left and right arrows.

Include the controller buttons like you would add the "clear" button as a right icon, and then wrap them with a div.flix-input__controllers.

Pay attention to the proper usage of aria attributes, since these controllers change the value of the input field you must associate them using aria-controls="<the-input-id>".

<form class="flix-form-row flix-grid">
  <div class="flix-col-6">
    <div class="flix-input flix-input--has-controllers">
      <label class="flix-label flix-input__label" for="control-departure-example">
        Departure
      </label>
      <div class="flix-input__container">
        <input class="flix-input__field" id="control-departure-example" type="date" value="1977-09-05"/>
        <span class="flix-input__feedback-icon" aria-hidden="true"></span>
        <div class="flix-input__controllers">
          <button type="button" aria-label="Previous departure day" aria-controls="control-departure-example" class="flix-input__icon flix-btn flix-btn--link flix-btn--square flix-btn--sm">
            <i class="flix-btn__icon flix-icon flix-icon-arrow-left" aria-hidden="true"></i>
          </button>
          <button type="button" aria-label="Next departure day" aria-controls="control-departure-example" class="flix-input__icon flix-btn flix-btn--link flix-btn--square flix-btn--sm">
            <i class="flix-btn__icon flix-icon flix-icon-arrow-right" aria-hidden="true"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
  <div class="flix-col-6">
    <div class="flix-input flix-input--has-controllers">
      <label class="flix-label flix-input__label" for="control-arrival-example">
        Arrival
      </label>
      <div class="flix-input__container">
        <input class="flix-input__field" id="control-arrival-example" type="date" value="1977-09-06"/>
        <span class="flix-input__feedback-icon" aria-hidden="true"></span>
        <div class="flix-input__controllers">
          <button type="button" aria-label="Previous arrival day" aria-controls="control-arrival-example" class="flix-input__icon flix-btn flix-btn--link flix-btn--square flix-btn--sm">
            <i class="flix-btn__icon flix-icon flix-icon-arrow-left" aria-hidden="true"></i>
          </button>
          <button type="button" aria-label="Next arrival day" aria-controls="control-arrival-example" class="flix-input__icon flix-btn flix-btn--link flix-btn--square flix-btn--sm">
            <i class="flix-btn__icon flix-icon flix-icon-arrow-right" aria-hidden="true"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</form>

Inline labels

Inline labels work similar to icons, you should add them inside of the input container and their position is dictated by the order they appear inside of the document.

But unlike the icons, the inline labels deliver important information related to the input field format, for this reason you must connect them to the field for screen reader support.

  • Add the inline label text inside of a flix-input__inline-label element
  • Add an id to the inline label element
  • Connect it to the field by using aria-describedby="{ID}" on the field

This way, when screen reader users focus the input field the screen reader will be able to read out the inline label together with the input label and any error messages it contains.

EUR
How much do you want to spend this month in Europe
<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="budget-eur">
      Budget
    </label>
    <div class="flix-input__container">
      <span class="flix-input__inline-label" id="budget-eur-description">
        EUR
      </span>
      <i class="flix-input__icon flix-icon flix-icon-cash" aria-hidden="true"></i>
      <input type="number" id="budget-eur" class="flix-input__field" aria-describedby="budget-eur-description budget-eur-info" value="20.50"/>
    </div>
    <span class="flix-input__info" id="budget-eur-info">
      How much do you want to spend this month in Europe
    </span>
  </div>
</div>

Showing the inline label to the right simply required you to move the element bellow the input field, no extra modifiers required:

USD
How much do you want to spend this month in the United States
<div class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label" for="budget-usd">
      Budget
    </label>
    <div class="flix-input__container">
      <i class="flix-input__icon flix-icon flix-icon-cash" aria-hidden="true"></i>
      <input type="number" id="budget-usd" class="flix-input__field" aria-describedby="budget-usd-description budget-usd-info" value="20.50"/>
      <span class="flix-input__inline-label" id="budget-usd-description">
        USD
      </span>
    </div>
    <span class="flix-input__info" id="budget-usd-info">
      How much do you want to spend this month in the United States
    </span>
  </div>
</div>

Feedback, validation and errors

When dealing with form errors it is important to deliver clear feedback and error messages that are easy to understand so users can tackle them without stress.

The feedback icons provide visual feedback while the info messages deliver text based details of how to correct the error that are accessible when implemented correctly.

First of all, make sure that all required fields have the required attribute to them. This can be used for form validation and also tell screen reader users that that field is mandatory.

Error state

  • Add the --error modifier to the component to trigger the visual appearance
  • Add aria-invalid="true" attribute to the input field to display the icon and communicate to assistive technologies that this field requires attention
  • If an error message is needed, the first flix-input__info will be used to deliver it:
    • Give it an id
    • Add the aria-live="assertive" attribute to it, this allows assistive technologies to announce it as soon as the error happens
    • Connect the error message with the invalid input using the aria-errormessage attribute
    • You can keep the element in the document and add or remove the content from it, aria-live will take care of announcing changes to this element whenever it changes
This field is required Only letters and some special characters are allowed
<div class="flix-form-row">
  <div class="flix-input flix-input--error">
    <label class="flix-label flix-input__label" for="first-name-2">
      Name
    </label>
    <div class="flix-input__container">
      <input type="text" id="first-name-2" class="flix-input__field" required="" aria-invalid="true" aria-errormessage="first-name-2-error" aria-describedby="first-name-2-info"/>
      <span class="flix-input__feedback-icon" aria-hidden="true"></span>
    </div>
    <span class="flix-input__info" id="first-name-2-error" aria-live="assertive">
      This field is required
    </span>
    <span class="flix-input__info" id="first-name-2-info">
      Only letters and some special characters are allowed
    </span>
  </div>
</div>

Valid state

After the user fixes an input that had an error, marking the input as valid is pretty easy:

  • Change the modifier to --valid to trigger the visual appearance
  • Switch the input field aria-invalid attribute to "false"
  • When the error message is no longer needed, you can remove the content of the error message element
Only letters and some special characters are allowed
<div class="flix-form-row">
  <div class="flix-input flix-input--valid">
    <label class="flix-label flix-input__label" for="first-name-3">
      Name
    </label>
    <div class="flix-input__container">
      <input type="text" id="first-name-3" class="flix-input__field" required="" aria-invalid="false" aria-errormessage="first-name-3-error" aria-describedby="first-name-3-info" value="Pikachu"/>
      <span class="flix-input__feedback-icon" aria-hidden="true"></span>
    </div>
    <span class="flix-input__info" id="first-name-3-error" aria-live="assertive"></span>
    <span class="flix-input__info" id="first-name-3-info">
      Only letters and some special characters are allowed
    </span>
  </div>
</div>

Loading state

On certain circumstances the input may be in a loading state, for example: searching for autocomplete results or checking the validity of an e-mail. In any case, to show the loading state can follow these steps:

  • Add the --loading modifier to trigger the feedback icon appearance
  • Set the attribute aria-busy="true" to the input field for screen reader support
  • Make sure to set aria-busy="false" whenever the loading state ends
  • If the loading state generates a change in validation state (e.g.: invalid e-mail) you can keep all aria attributes in the field and update them according to the current state
Checking your e-mail...
<div class="flix-form-row">
  <div class="flix-input flix-input--loading">
    <label class="flix-label flix-input__label" for="email">
      E-mail
    </label>
    <div class="flix-input__container">
      <input type="email" id="email" class="flix-input__field" required="" aria-busy="true" aria-describedby="email-info" value="pikachu@kanto.jp"/>
      <span class="flix-input__feedback-icon" aria-hidden="true"></span>
    </div>
    <span class="flix-input__info" id="email-error" aria-live="assertive"></span>
    <span class="flix-input__info" id="email-info">
      Checking your e-mail...
    </span>
  </div>
</div>

Search fields

The search field is usually a very important feature, there are some tricks that will make your search form easily accessible by all users.

  • Use the role="search" in the form around the search field
  • Add an accessible label to the search form element, e.g: site wite search, city filter
  • Use the type="search" as the input field type to enable browser autocomplete and history searches
  • If you want to hide the input label, use the flix-sr-only helper on the label to make it visually hidden, but still be accessible by screen readers
  • Typically search fields come accompanied by a magnifier icon, so make sure to add it
<form role="search" class="flix-form-row">
  <div class="flix-input">
    <label class="flix-label flix-input__label flix-sr-only" for="site-search">
      Search website:
    </label>
    <div class="flix-input__container">
      <i class="flix-input__icon flix-icon flix-icon-magnifier" aria-hidden="true"></i>
      <input type="search" id="site-search" class="flix-input__field" placeholder="Search..." required=""/>
    </div>
  </div>
</form>