Skip to main content

Looking for the web component? See Select (web component)

Variations

The following configuration demonstrates a bare-minimum select pattern. All other variations are modifications of this configuration.

<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-default">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
  </div>
  <select id="select-default">
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-disabled">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
  </div>
  <select 
    id="select-disabled"
    disabled
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
<bolt-select-control class="bolt-invalid">
  <div class="bolt-label-wrapper">
    <label for="select-invalid">Select menu name</label>
  </div>
  <select
    aria-describedby="select-error"
    id="select-invalid"
    required
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
  <footer>
    <bolt-field-error id="select-error">
      You must select an option.
    </bolt-field-error>
  </footer>
</bolt-select-control>
<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-with-help">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
    <bolt-contextual-help
      heading="Help text heading"
      type="push"
    >
      <p>Help text body content.</p>
    </bolt-contextual-help>
  </div>
  <select id="select-with-help">
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-with-help-disabled">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
    <bolt-contextual-help
      disabled
      heading="Help text heading"
      type="push"
    >
      <p>Help text body content.</p>
    </bolt-contextual-help>
  </div>
  <select
    disabled
    id="select-with-help-disabled"
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>

By default, the select box fills the width of the bolt-select-control element.

To set an explicit width on the select box only, the select and bolt-select-facade elements must have the same width. The example below demonstrates how to set an explicit width for the select box. While the example uses the style attribute, it is recommended to use a CSS class to set the width of both elements.

<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-explicit-width">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
  </div>
  <select 
    id="select-explicit-width"
    style="width: 320px;"
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade style="width: 320px;"></bolt-select-facade>
</bolt-select-control>

To display the selected option text below the select box, logic must be implemented by the consumer. The example below demonstrates how to implement the logic using JavaScript.

<bolt-select-control>
  <div class="bolt-label-wrapper">
    <label for="select-long-option">
      Fund name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
  </div>
  <select 
    id="select-long-option"
    style="width: 320px;"
  >
    <option value="">Select</option>
    <option value="item1">Nationwide AllianzGI International Growth Fund</option>
    <option value="item2">Nationwide Bailard International Equities Fund Equity Funds</option>
    <option value="item3">Nationwide Global Sustainable Equity Fund</option>
  </select>
  <bolt-select-facade style="width: 320px;"></bolt-select-facade>
  <footer>
    <div
      aria-hidden="true"
      class="bolt-select-long-option-text"
      id="selectedValueText"
    ></div>
  </footer>
</bolt-select-control>
<script>
  let displayValue = document.querySelector('#selectedValueText');
  let select = document.querySelector('#select-long-option');
  select.addEventListener('change', function() {
    if (select.value) {
      displayValue.textContent = select.options[select.selectedIndex].text;
    } else {
      displayValue.textContent = '';
    }
  });
</script>
<bolt-select-control class="bolt-select-fit-content">
  <div class="bolt-label-wrapper">
    <label for="select-fit-content">
      Select menu name
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>
  </div>
  <select id="select-fit-content">
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
<p id="select-label">Select menu name</p>
<bolt-select-control>
  <select
    aria-labelledby="select-label"
    id="select-with-labelledby"
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
<bolt-select-control>
  <select
    aria-label="Select menu name"
    id="select-with-arialabel"
  >
    <option value="">Select</option>
    <option value="item1">Item one</option>
    <option value="item2">Item two</option>
    <option value="item3">Item three</option>
  </select>
  <bolt-select-facade></bolt-select-facade>
</bolt-select-control>
Code reference

The HTML implementation provides maximum control over the markup. However, it is up to the consumer to implement all advanced interaction logic.

If you want Bolt to handle the interaction logic, check out the web component implementation.

This implementation should be compatible with @angular/forms without the need for additional dependencies.

The <bolt-select-facade> custom element is designed exclusively for use within the select control pattern in order to encapsulate the complex CSS required to present a styled select control.

All APIs built for <bolt-select-facade> should be considered "private" and are subject to change at any time, without warning. Any use of the custom element outside of documented patterns shall be done so at consumer's own risk.

<!-- Root (REQUIRED) -->
<bolt-select-control
  class="
    [bolt-invalid]
    [bolt-select-fit-content]
  "
>
  <!-- Label wrapper (REQUIRED, unless using aria-label or aria-labelledby) -->
  <div class="bolt-label-wrapper">

    <!-- Label (REQUIRED) -->
    <label for="SELECT_ID">
      Label text

      <!-- Annotation (optional) -->
      <span class="bolt-annotation bolt-optional">(optional)</span>
    </label>

    <!-- Contextual help (optional) -->
    <bolt-contextual-help
      [disabled]
      heading="Heading"
      type="push"
      ...
    >
      ...
    </bolt-contextual-help>
  </div>

  <!-- Select (REQUIRED) -->
  <select
    [aria-describedby="ERRORS_ID"]
    [disabled]
    [required]
    id="SELECT_ID"
    ...
  >
    <option value="">Select</option>
    <option value="1" [selected]>Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
  </select>

  <!-- Facade (REQUIRED) -->
  <bolt-select-facade></bolt-select-facade>

  <!-- Footer (optional) -->
  <footer>

    <!-- Long option text display (optional) -->
    <div
      aria-hidden="true"
      class="[bolt-select-long-option-text]"
    ></div>

    <!-- Error (optional) -->
    <bolt-field-error id="ERRORS_ID">...</bolt-field-error>
  </footer>

</bolt-select-control>

Unless specified, elements should be defined in the order presented above.

A select control is comprised of the following items:

  • Root (REQUIRED)
    • MAY apply .bolt-invalid class to apply "invalid" appearance to the select element.
    • MAY apply .bolt-select-fit-content class to set the width of the select element based on the longest option.
  • Label wrapper (REQUIRED, unless using aria-label or aria-labelledby on <select>)
    • MUST apply .bolt-label-wrapper class to ensure proper layout of label element with any optional items.
  • Label (REQUIRED)
    • MUST have a [for] attribute with value matching the [id] of the select.
    • MUST be first item inside <div class="bolt-label-wrapper"> element.
  • Annotation (optional)
    • When present, communicates that selecting an option is not critical for workflow progression.
    • MUST match .bolt-annotation.bolt-optional CSS selector.
    • MUST be an inline element inside of label element.
    • Should have "(optional)" as inner text.
  • Contextual help (optional)
    • MUST have [type="push"].
    • MUST be last item inside <div class="bolt-label-wrapper"> element.
    • See contextual help component for more information.
  • Select (REQUIRED)
    • MUST have an [id] attribute.
    • Refer to MDN for best practices on using the HTML <select> element.
  • Facade (REQUIRED)
    • MUST be present to display the select on screen.
  • Footer (optional)
    • Supports wrapping optional elements to be associated with the select.
  • Long option text display (optional)
    • Placeholder element to display the text of the selected option below the select box.
    • MUST apply .bolt-select-long-option-text class to style the text.
    • MUST be wrapped in the footer.
    • MUST implement logic to display the selected option text in this placeholder element.
  • Error (optional)
    • Defines a single error message.
    • A <bolt-field-error> element is recommended.
    • MUST have an [id] attribute that matches the [aria-describedby] attribute of the select.
    • MUST be wrapped in the footer.
    • Error and disabled state should not be used at the same time.
Design guidelines
  • Select is used for selecting one item from a list of between 6 and 15 items. Avoid overwhelming users with too many options.
  • Order the options in a Select logically.
  • Only if a deliberate selection is required or if no option can be defaulted, should a Select display the placeholder text "Select" before a user interacts with it. Otherwise, any available option can be set as the Select's default.
  • Combine a Select with a field label for context and the best accessibility. A field label is not needed when the component is used in a table. (e.g. where a column header provides accessible context.)
  • When a screen does not provide enough space for a user to see the full text of an option, place the text, in full, below the Select to let the user know what they have chosen.
  • Input validation and error messaging for a Select should only occur after a user submits a form.
  • Select should never be in both error and disabled states at the same time.
  • When a user needs to choose one option from a simple list of 6 or more options.
  • Use Select if space constraints don't allow a large number of radio buttons to be used for selecting one option.
  • Avoid using a Select when typing may be faster.
  • Avoid if all options are required to be displayed concurrently.
  • Avoid Select when displaying more than 15 options; consider using a Text field or Autocomplete, especially if filtering would be beneficial.
  • Consider an alternative pattern when options are links navigating users to various places.
  • Consider using Radio button for a list between 2 and 5 predefined options when space is available.
  • Use Radio button instead of Select for a single boolean option.
  • Use Switch for a binary decision where the input can be recorded or updated immediately.
  • Use Checkbox for user confirmation (e.g., "I agree to…" or "I have read…") instead of Select.

Do

  • Order options in Select logically.
  • Display a user's selected option after a choice is made.
  • Have clear, short field labels that provide users with an idea of the options they will see before opening a Select.

Don't

  • Don't disable options; hide them instead.
  • Don't add subtext or images into a Select.
  • Don't add too many options; but at least 6 options are recommended.
  • Don't allow choosing an item from a Select to act as navigation. Allow the user to make a choice and then press a button to proceed.
  • Select field labels and items use sentence case.
  • Error messages use sentence case and include a period.
Accessibility

In addition to code requirements, the following guidelines should be taken into account to ensure maximum accessibility.

  • A select control MUST define an accessible label via one of the following strategies:
    • label element with for attribute that matches the [id] of the select.
    • aria-label attribute on the select element.
    • aria-labelledby attribute on the select element.

Display settings

Note: not all settings persist across pages

Default Compact (-1) Sparse (+1) XL (default) 2XL 3XL Default Min Max Light (default) System Dark Branded (default) Unbranded