Forms

The Input class applies Champion branding to most text-based form elements.

<input class="Input" type="text" value="Text">
<input class="Input" type="search" placeholder="Search by keyword…">
<input class="Input" type="email" value="info@championpowerequipment.com">
<input class="Input" type="date" value="2017-05-17">
<input class="Input" type="number" value="9000" pattern="[0-9]*" inputmode="numeric">
<input class="Input" type="file">
<input class="Input" type="file" disabled>
<input class="Input" type="text" value="Disabled" disabled>
<input class="Input" type="text" value="Read-only" readonly>
<select class="Input">
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</select>
<textarea class="Input">Champion’s totally automatic solution provides security, convenience, health and safety — all things that every homeowner holds dear. Don’t put these things at risk during a power outage. Millions of individuals suffer from the effects of a power outage annually.
</textarea>

The following cosmetic modifiers are available for different scenarios:

  • Input--contrast adjusts border and focus colors for display against saturated colors.
  • Input--onDark optimized border and focus colors for darker backgrounds.
  • Input--success for validated form fields.
  • Input--danger for invalid form fields.
  • Input--withDropdown for JavaScript interactions that use an <input> element to trigger a dropdown.

Input Group

  • javascript

Inputs and buttons may be visually "joined" using the InputGroup pattern and associated child classes:

  • InputGroup-input for text-based input elements.
  • InputGroup-action for buttons or other actionable elements.
  • InputGroup-iconLabel for iconographic labels that appear inset in adjacent InputGroup-input elements.

Works well with existing Input and Button patterns, though they aren't strictly required.

If you add js-InputGroup and js-InputGroup-input classes and there is only one of the latter, focus ring of the input will surround the entire group. Be sure to add the InputGroup--contrast modifier if the Input--contrast modifier is in use.

<div class="u-pad1">
  <div class="InputGroup js-InputGroup">
    <label class="InputGroup-iconLabel" for="demo-input-group">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-input-group-label" class="Icon">
        <title id="demo-input-group-label">Label text</title>

        <path d="M28 11.094v12.406c0 1.375-1.125 2.5-2.5 2.5h-23c-1.375 0-2.5-1.125-2.5-2.5v-12.406c0.469 0.516 1 0.969 1.578 1.359 2.594 1.766 5.219 3.531 7.766 5.391 1.313 0.969 2.938 2.156 4.641 2.156h0.031c1.703 0 3.328-1.188 4.641-2.156 2.547-1.844 5.172-3.625 7.781-5.391 0.562-0.391 1.094-0.844 1.563-1.359zM28 6.5c0 1.75-1.297 3.328-2.672 4.281-2.438 1.687-4.891 3.375-7.313 5.078-1.016 0.703-2.734 2.141-4 2.141h-0.031c-1.266 0-2.984-1.437-4-2.141-2.422-1.703-4.875-3.391-7.297-5.078-1.109-0.75-2.688-2.516-2.688-3.938 0-1.531 0.828-2.844 2.5-2.844h23c1.359 0 2.5 1.125 2.5 2.5z" />
      </svg> </label>
    <input class="Input InputGroup-input js-InputGroup-input" type="text" placeholder="Example" id="demo-input-group">
    <button class="Button InputGroup-action">
      Action
    </button>
  </div>
</div>

<div class="u-bgBlack u-pad1">
  <div class="InputGroup js-InputGroup">
    <label class="InputGroup-iconLabel" for="demo-input-group">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-input-group-label" class="Icon">
        <title id="demo-dark-input-group-label">Label text</title>

        <path d="M28 11.094v12.406c0 1.375-1.125 2.5-2.5 2.5h-23c-1.375 0-2.5-1.125-2.5-2.5v-12.406c0.469 0.516 1 0.969 1.578 1.359 2.594 1.766 5.219 3.531 7.766 5.391 1.313 0.969 2.938 2.156 4.641 2.156h0.031c1.703 0 3.328-1.188 4.641-2.156 2.547-1.844 5.172-3.625 7.781-5.391 0.562-0.391 1.094-0.844 1.563-1.359zM28 6.5c0 1.75-1.297 3.328-2.672 4.281-2.438 1.687-4.891 3.375-7.313 5.078-1.016 0.703-2.734 2.141-4 2.141h-0.031c-1.266 0-2.984-1.437-4-2.141-2.422-1.703-4.875-3.391-7.297-5.078-1.109-0.75-2.688-2.516-2.688-3.938 0-1.531 0.828-2.844 2.5-2.844h23c1.359 0 2.5 1.125 2.5 2.5z" />
      </svg> </label>
    <input class="Input InputGroup-input Input--onDark js-InputGroup-input" type="text" placeholder="Dark Example" id="demo-dark-input-group">
    <button class="Button InputGroup-action u-bgSilver u-textBlack">
      Action
    </button>
  </div>
</div>

<div class="u-bgYellow u-pad1">
  <div class="InputGroup js-InputGroup InputGroup--contrast">
    <label class="InputGroup-iconLabel" for="demo-input-group">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-input-group-label" class="Icon">
        <title id="demo-contrast-input-group-label">Label text</title>

        <path d="M28 11.094v12.406c0 1.375-1.125 2.5-2.5 2.5h-23c-1.375 0-2.5-1.125-2.5-2.5v-12.406c0.469 0.516 1 0.969 1.578 1.359 2.594 1.766 5.219 3.531 7.766 5.391 1.313 0.969 2.938 2.156 4.641 2.156h0.031c1.703 0 3.328-1.188 4.641-2.156 2.547-1.844 5.172-3.625 7.781-5.391 0.562-0.391 1.094-0.844 1.563-1.359zM28 6.5c0 1.75-1.297 3.328-2.672 4.281-2.438 1.687-4.891 3.375-7.313 5.078-1.016 0.703-2.734 2.141-4 2.141h-0.031c-1.266 0-2.984-1.437-4-2.141-2.422-1.703-4.875-3.391-7.297-5.078-1.109-0.75-2.688-2.516-2.688-3.938 0-1.531 0.828-2.844 2.5-2.844h23c1.359 0 2.5 1.125 2.5 2.5z" />
      </svg> </label>
    <input class="Input InputGroup-input Input--contrast js-InputGroup-input" type="text" placeholder="Contrast Example" id="demo-contrast-input-group">
    <button class="Button InputGroup-action">
      Action
    </button>
  </div>
</div>

Custom checkbox and radio styles optimized for easier touch behavior and more branded appearance. Works using a hidden <input> and adjacent selectors, which gives much more consistent behavior without requiring JavaScript.

<p>
  <label class="Toggle u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="checkbox" id="patterns.elements.forms.toggles" name="Toggles" checked>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Checkbox (Checked)
    </span>
  </label>
</p>
<p>
  <label class="Toggle u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="checkbox" id="patterns.elements.forms.toggles" name="Toggles">
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Checkbox
    </span>
  </label>
</p>
<p>
  <label class="Toggle u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="checkbox" id="patterns.elements.forms.toggles" name="Toggles" checked disabled>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Disabled Checkbox (Checked)
    </span>
  </label>
</p>
<p>
  <label class="Toggle u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="checkbox" id="patterns.elements.forms.toggles" name="Toggles" disabled>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Disabled Checkbox
    </span>
  </label>
</p>
<p>
  <label class="Toggle Toggle--radio u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="radio" id="patterns.elements.forms.toggles" name="drizzleRadioDemo" checked>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Radio 1
    </span>
  </label>
</p>
<p>
  <label class="Toggle Toggle--radio u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="radio" id="patterns.elements.forms.toggles" name="drizzleRadioDemo">
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Radio 2
    </span>
  </label>
</p>
<p>
  <label class="Toggle Toggle--radio u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="radio" id="patterns.elements.forms.toggles" name="drizzleRadioDemoDisabled" checked disabled>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Disabled Radio 1 (Checked)
    </span>
  </label>
</p>
<p>
  <label class="Toggle Toggle--radio u-flex u-flexAlignItemsCenter">
    <input class="Toggle-state " type="radio" id="patterns.elements.forms.toggles" name="drizzleRadioDemoDisabled" disabled>
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Disabled Radio 2
    </span>
  </label>
</p>

Toggles have a few more tricks up their sleeve.

You can add Toggle to a non-<label> element by including the <label> as a child with the class Toggle-delegate. This also allows you to add the Toggle-expand class to a different adjacent element, allowing you to toggle the visibility of a sibling for simple progressive disclosure form fields without JavaScript.

<div class="Toggle u-flex u-flexAlignItemsCenter">
  <input class="Toggle-state " type="checkbox" id="window-ac-unit">
  <label class="Toggle-delegate u-flex u-flexAlignItemsCenter" for="window-ac-unit">
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text"> Window AC Unit
    </span>
  </label>
  <div class="Toggle-expand u-flexExpandLeft u-size1of6 u-pullEnds01">
    <label class="u-hiddenVisually" for="count-window-ac-unit">
      Amount
    </label>
    <input class="Input" type="number" value="1" id="count-window-ac-unit">
  </div>
</div>

Add a Toggle-expand--disclosure modifier class to the Toggle-expand element to show a disclosure indicator in the form of a gray line enclosing the expanded content.

<div class="Toggle">
  <input class="Toggle-state" type="checkbox" id="more-info-needed">
  <label class="Toggle-delegate u-flex u-flexAlignItemsCenter" for="more-info-needed">
    <span class="Toggle-indicator u-spaceRight06" aria-hidden="true"></span>
    <span class="Toggle-text">A different retailer…</span>
  </label>
  <div class="Toggle-expand Toggle-expand--disclosure u-spaceTop1 u-spaceItems06">
    <label for="purchase-retailer" class="u-textWeightBold">Retailer name</label>
    <input class="Input" id="purchase-retailer">
  </div>
</div>

Input Results

  • javascript

The Input Results component allows you to display filtered results in a dropdown as the customer types in their search. Depending on your needs you can prepopulate the dropdown, or use AJAX Ajax to hit a search endpoint.

The component is composed of the following elements:

  • InputResults - Containing element
  • InputResults--overlay - Optional modifier that makes the dropdown overlay surrounding content instead of increasing the container height
  • InputResults-item - An individual result, assumed to be an <a> element
  • InputResults-object - Optional container for a visual element in an item, for example an icon or thumbnail
  • InputResults-label - The actual text for the item
  • InputResults-muted - An element that will appear lighter in color until the item is interacted with via hover or focus

Disabled Inputs: Adding is-disabled to InputResults-item will visually render that item with a disabled appearance and cursor behavior.

There are a handful of configuration options that can be passed in via data attributes:

  • data-url - the AJAX endpoint url
  • data-prepopulated - Whether the dropdown is prepopulated
  • data-close-outside - Whether to close the dropdown when a user clicks outside of it
  • data-delay - When using AJAX, how long to wait between AJAX calls
  • data-min-length - When using AJAX, how many characters must be typed before searching
  • data-key - When using AJAX this is the name of the search query string parameter

Add a data-url to enable the AJAX search option.

This example endpoint will always return the same data. When using this on a real site the endpoint would return filtered search data.

<div class="InputResults js-InputResults" data-url="/prototype-endpoints/input-results.json">
  <input class="Input js-InputResults-input" type="search" placeholder="Type to see…">
  <ul class="InputResults-dropdown js-InputResults-dropdown" aria-hidden="true"></ul>
</div>

The Input Results component is often used to allow searching a series of links, but it can be used as an enhanced <select> dropdown as well.

To get this to work make sure each InputResults-item is a <button>, not a link. Then add a data-val attribute to each button.

When a customer clicks a button the input will be populated with the data-val and the dropdown will close.

You can also add the Input--withDropdown modifier to the Input for a visual cue.

<div class="InputResults js-InputResults" data-prepopulated="true" data-close-outside="true">
  <input class="Input js-InputResults-input Input--withDropdown" type="text" placeholder="Type to see…">
  <ul class="InputResults-dropdown js-InputResults-dropdown" aria-hidden="true">
    <li>
      <button type="button" class="InputResults-item js-InputResults-item" data-val="123456">
        <div class="InputResults-object">
          <img src="/images/prototypes/generators/42436_hero-8_26_13_hi-res.jpg" alt="">
        </div>
          <div class="InputResults-label js-InputResults-searchable">
            <p class="InputResults-muted u-textShrink1 u-textTruncate">Model #123456</p>
            <p class="u-textTruncate">Not Really a Product Name</p>
          </div>
      </button>
    </li>
    <li>
      <button type="button" class="InputResults-item is-disabled js-InputResults-item" data-val="123456">
        <div class="InputResults-object">
          <img src="/images/prototypes/generators/42436_hero-8_26_13_hi-res.jpg" alt="">
        </div>
          <div class="InputResults-label js-InputResults-searchable">
            <p class="InputResults-muted u-textShrink1 u-textTruncate">Model #123456</p>
            <p class="u-textTruncate">Product Coming Soon</p>
          </div>
      </button>
    </li>
    <li>
      <button type="button" class="InputResults-item js-InputResults-item" data-val="Fictional Category Name">
        <div class="InputResults-label">
          <p class="InputResults-muted u-textShrink1 u-textTruncate">Product Category</p>
          <p class="u-textTruncate js-InputResults-searchable">Fictional Category Name</p>
        </div>
      </button>
    </li>
    <li>
      <button type="button" class="InputResults-item js-InputResults-item" data-val="Fake File">
        <div class="InputResults-object">
          <svg class="FileIcon FileIcon--pdf " viewBox="-4 0 42 48" width="42" height="48">
            <polygon class="FileIcon-base" points="38 48 0 48 0 0 26 0 38 12 38 48" />
            <polygon class="FileIcon-front" points="35 45 3 45 3 3 22 3 22 16 35 16 35 45" fill="#fff" />
            <polygon class="FileIcon-fold" points="25 3 35 13 25 13 25 3" fill="#fff" />
            <rect class="FileIcon-badge" x="-4" y="21" width="34" height="18" rx="3" />
            <text class="FileIcon-label" text-anchor="middle" x="13" y="34" font-size="12" fill="#fff">PDF</text>
          </svg>

        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="u-textTruncate">Fake File</p>
        </div>
      </button>
    </li>
    <li>
      <button disabled type="button" class="InputResults-item js-InputResults-item" data-val="Disabled Item">
        <div class="InputResults-object">
          <svg class="FileIcon FileIcon--pdf " viewBox="-4 0 42 48" width="42" height="48">
            <polygon class="FileIcon-base" points="38 48 0 48 0 0 26 0 38 12 38 48" />
            <polygon class="FileIcon-front" points="35 45 3 45 3 3 22 3 22 16 35 16 35 45" fill="#fff" />
            <polygon class="FileIcon-fold" points="25 3 35 13 25 13 25 3" fill="#fff" />
            <rect class="FileIcon-badge" x="-4" y="21" width="34" height="18" rx="3" />
            <text class="FileIcon-label" text-anchor="middle" x="13" y="34" font-size="12" fill="#fff">PDF</text>
          </svg>

        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="u-textTruncate">Disabled Item</p>
        </div>
      </button>
    </li>
  </ul>
</div>

In some cases it's more performant to prepopulate the dropdown and perform filtering and searching client-side. To enable this remove the data-url and add data-prepopulated="true" .When using the prepopulated option, the following settings are ignored:

  • data-url
  • data-delay
  • data-min-length

The text to search for matches should be wrapped in the js-InputResults-searchable class. Anything outside of that class will be ignored when searching.

<div class="InputResults js-InputResults" data-prepopulated="true" data-close-outside="true">
  <input class="Input js-InputResults-input Input--withDropdown" type="search" placeholder="Type to see…">
  <ul class="InputResults-dropdown js-InputResults-dropdown" aria-hidden="true">
    <li>
      <a href="#" type="button" class="InputResults-item js-InputResults-item">
        <div class="InputResults-object">
          <img src="/images/prototypes/generators/42436_hero-8_26_13_hi-res.jpg" alt="">
        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="InputResults-muted u-textShrink1 u-textTruncate">Model #123456</p>
          <p class="u-textTruncate">Not Really a Product Name</p>
        </div>
      </a>
    </li>
    <li>
      <a href="#" type="button" class="InputResults-item is-disabled js-InputResults-item">
        <div class="InputResults-object">
          <img src="/images/prototypes/generators/42436_hero-8_26_13_hi-res.jpg" alt="">
        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="InputResults-muted u-textShrink1 u-textTruncate">Model #123456</p>
          <p class="u-textTruncate">Product Coming Soon</p>
        </div>
      </a>
    </li>
    <li>
      <a href="#" type="button" class="InputResults-item js-InputResults-item">
        <div class="InputResults-label">
          <p class="InputResults-muted u-textShrink1 u-textTruncate">Product Category</p>
          <p class="u-textTruncate js-InputResults-searchable">Fictional Category Name</p>
        </div>
      </a>
    </li>
    <li>
      <a href="#" type="button" class="InputResults-item js-InputResults-item">
        <div class="InputResults-object">
          <svg class="FileIcon FileIcon--pdf " viewBox="-4 0 42 48" width="42" height="48">
  <polygon class="FileIcon-base" points="38 48 0 48 0 0 26 0 38 12 38 48"/>
  <polygon class="FileIcon-front" points="35 45 3 45 3 3 22 3 22 16 35 16 35 45" fill="#fff"/>
  <polygon class="FileIcon-fold" points="25 3 35 13 25 13 25 3" fill="#fff"/>
  <rect class="FileIcon-badge" x="-4" y="21" width="34" height="18" rx="3"/>
  <text class="FileIcon-label" text-anchor="middle" x="13" y="34" font-size="12" fill="#fff">PDF</text>
</svg>

        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="u-textTruncate">Fake File</p>
        </div>
      </a>
    </li>
    <li>
      <button disabled type="button" class="InputResults-item js-InputResults-item">
        <div class="InputResults-object">
          <svg class="FileIcon FileIcon--pdf " viewBox="-4 0 42 48" width="42" height="48">
            <polygon class="FileIcon-base" points="38 48 0 48 0 0 26 0 38 12 38 48" />
            <polygon class="FileIcon-front" points="35 45 3 45 3 3 22 3 22 16 35 16 35 45" fill="#fff" />
            <polygon class="FileIcon-fold" points="25 3 35 13 25 13 25 3" fill="#fff" />
            <rect class="FileIcon-badge" x="-4" y="21" width="34" height="18" rx="3" />
            <text class="FileIcon-label" text-anchor="middle" x="13" y="34" font-size="12" fill="#fff">PDF</text>
          </svg>

        </div>
        <div class="InputResults-label js-InputResults-searchable">
          <p class="u-textTruncate">Disabled Item</p>
        </div>
      </button>
    </li>
  </ul>
</div>

Add js-ElasticTextarea to a <textarea> element to have it expand as the user types more than will fit.

  • If the rows attribute is set, it will be used as the minimum height.
<textarea class="Input js-ElasticTextarea" placeholder="Type stuff"></textarea>