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.

name

  • 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-name">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-name-label" class="Icon">        <title id="demo-name-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-name">
          <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-name">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-name-label" class="Icon">        <title id="demo-dark-name-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-name">
          <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-name">
      <svg width="28" height="28" viewBox="0 0 28 28" aria-labelledby="demo-name-label" class="Icon">        <title id="demo-contrast-name-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-name">
          <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"
          
          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"
          
          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"
          
          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"
          
          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"
          
          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"
          
          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"
          
          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"
          
          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>