Skip to main content

Your privacy settings

We use cookies to help you with journey planning and relevant disruptions, remember your login and show you content you might be interested in. If you’re happy with the use of cookies by West Midlands Combined Authority and our selected partners, click ‘Accept all cookies’. Or click ‘Manage cookies’ to learn more.

Manage Cookies
Beta

This is a new service - your feedback will help us to improve it.

Patterns

Search

What does it do?

  • Allows the user to search for information across the Transport for West Midlands website

When to use it?

  • When a user needs to find the information they need, which they cannot find through the main navigation

How it works

  • Users should only be able to access the search function through the header by hovering or selecting the magnifying glass icon
  • The search bar will appear in a dropdown along with the ‘I want to…’ feature, where users can access popular search queries
  • Once a user submits their search query, they will be able to view the search results. They can sort and filter the search results on the search results page


Search bar



HTML markup
<form class="wmnds-search-bar">
  <input aria-label="Search" type="text" class="wmnds-search-bar__input wmnds-fe-input" placeholder="Search for tickets, timetables, travel advice…">
  <button class="wmnds-search-bar__btn" type="submit">
    <svg>
      <title>Search</title>
      <use xlink:href="#wmnds-general-search" href="#wmnds-general-search"></use>
    </svg>
  </button>
</form>


Sort

What does it do?

  • This gives the user the option to sort search results by relevance or when a page was last updated


HTML markup
<div class="wmnds-search-sort wmnds-fe-group">
  <label class="wmnds-fe-label" for="dropdown">
    <h3>Sort by</h3>
  </label>
  <div class="wmnds-fe-dropdown">
    <select class="wmnds-fe-dropdown__select" id="dropdown" name="dropdown">
      <option value="" selected="selected">Choose from list</option>
      <option value="1">Relevance</option>
      <option value="2">Most recent</option>
      <option value="3">Oldest</option>
    </select>
  </div>
</div>


Filter

What does it do?

  • This gives the user the option to filter search results using a predetermined set of filters

When to use it?

  • The filters will narrow down the search results by displaying pages which only match the filter criteria
  • On mobile, the filter options will appear when a user clicks on the ‘Filter your results button’. This will trigger an overlay where users can select and apply filters. This is to reduce page size on smaller devices

Close Clear all filters

HTML markup
<!-- Mobile show filter button -->
<div class="wmnds-hide-desktop">
  <button class="wmnds-btn wmnds-btn--primary wmnds-btn--block " id="show_filter_btn" aria-controls="search_filter" aria-expanded="false">
    Filter your results
  </button>
</div>
<div id="search_filter" class="wmnds-search-filter">
  <div class="wmnds-search-filter__header">
    <h3 class="wmnds-search-filter__header-title">Filter</h3>
    <a href="#" class="wmnds-link wmnds-search-filter__clear-all">Clear all</a>
    <a href="#" id="hide_filter_btn" class="wmnds-search-filter__close">
      <svg>
        <title>Close</title>
        <use xlink:href="#wmnds-general-cross" href="#wmnds-general-cross"></use>
      </svg>
    </a>
  </div>
  <div class="wmnds-accordion">
    <button aria-controls="accordion-Topic" class="wmnds-accordion__summary-wrapper" aria-expanded="false">
      <!-- accordion summary -->
      <div class="wmnds-accordion__summary">
        <h4 class="wmnds-accordion__summary-title wmnds-m-b-none">Topic</h4>
      </div>
      <!-- plus icon -->
      <svg class="wmnds-accordion__icon">
        <use xlink:href="#wmnds-general-expand" href="#wmnds-general-expand"></use>
      </svg>
      <!-- minus icon -->
      <svg class="wmnds-accordion__icon wmnds-accordion__icon--minimise">
        <use xlink:href="#wmnds-general-minimise" href="#wmnds-general-minimise"></use>
      </svg>
    </button>
    <!-- accordion content -->
    <div class="wmnds-accordion__content" id="accordion-Topic">
      <fieldset class="wmnds-fe-fieldset">
        <div class="wmnds-fe-checkboxes">
          <label class="wmnds-fe-checkboxes__container">
            Tickets
            <input class="wmnds-fe-checkboxes__input" value="Tickets" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            Travel advice
            <input class="wmnds-fe-checkboxes__input" value="Travel advice" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            Planning a journey
            <input class="wmnds-fe-checkboxes__input" value="Planning a journey" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
        </div>
      </fieldset>
    </div>
  </div>
  <div class="wmnds-accordion">
    <button aria-controls="accordion-Page type" class="wmnds-accordion__summary-wrapper" aria-expanded="false">
      <!-- accordion summary -->
      <div class="wmnds-accordion__summary">
        <h4 class="wmnds-accordion__summary-title wmnds-m-b-none">Page type</h4>
      </div>
      <!-- plus icon -->
      <svg class="wmnds-accordion__icon">
        <use xlink:href="#wmnds-general-expand" href="#wmnds-general-expand"></use>
      </svg>
      <!-- minus icon -->
      <svg class="wmnds-accordion__icon wmnds-accordion__icon--minimise">
        <use xlink:href="#wmnds-general-minimise" href="#wmnds-general-minimise"></use>
      </svg>
    </button>
    <!-- accordion content -->
    <div class="wmnds-accordion__content" id="accordion-Page type">
      <fieldset class="wmnds-fe-fieldset">
        <div class="wmnds-fe-checkboxes">
          <label class="wmnds-fe-checkboxes__container">
            Services
            <input class="wmnds-fe-checkboxes__input" value="Services" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            News
            <input class="wmnds-fe-checkboxes__input" value="News" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            Bus routes
            <input class="wmnds-fe-checkboxes__input" value="Bus routes" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            Timetables
            <input class="wmnds-fe-checkboxes__input" value="Timetables" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
          <label class="wmnds-fe-checkboxes__container">
            Offers and promotions
            <input class="wmnds-fe-checkboxes__input" value="Offers and promotions" type="checkbox" />
            <span class="wmnds-fe-checkboxes__checkmark">
              <svg class="wmnds-fe-checkboxes__icon">
                <use xlink:href="#wmnds-general-checkmark" href="#wmnds-general-checkmark"></use>
              </svg>
            </span>
          </label>
        </div>
      </fieldset>
    </div>
  </div>
  <div class="wmnds-search-filter__mobile-filter-update wmnds-hide-desktop">
    <button id="show_results_btn" class="wmnds-btn wmnds-btn--block">Show 80 results</button>
  </div>
  <a href="#" class="wmnds-search-filter__clear-all wmnds-hide-mobile">
    <svg>
      <title>Close</title>
      <use xlink:href="#wmnds-general-cross" href="#wmnds-general-cross"></use>
    </svg> Clear all filters
  </a>
</div>

Recommended javascript (browser compatible)
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

function _toConsumableArray(arr) {
  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}

function _nonIterableSpread() {
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

function _iterableToArray(iter) {
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}

function _arrayWithoutHoles(arr) {
  if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;
  for (var i = 0, arr2 = new Array(len); i < len; i++) {
    arr2[i] = arr[i];
  }
  return arr2;
}

var searchFilterJs = function searchFilterJs() {
  var showBtn = document.getElementById('show_filter_btn');
  var hideBtn = document.getElementById('hide_filter_btn');
  var showResults = document.getElementById('show_results_btn');
  var searchFilter = document.getElementById('search_filter');

  if (searchFilter) {
    var filterOptions = searchFilter.querySelectorAll('.wmnds-fe-checkboxes__input');
    filterOptions.forEach(function(option) {
      option.addEventListener('change', function() {
        if (_toConsumableArray(filterOptions).some(function(input) {
            return input.checked;
          })) {
          searchFilter.classList.add('wmnds-search-filter--has-inputs-checked');
        } else {
          searchFilter.classList.remove('wmnds-search-filter--has-inputs-checked');
        }
      });
    });

    var showFilter = function showFilter() {
      var show = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;

      if (show) {
        searchFilter.classList.add('wmnds-search-filter--is-open');
        searchFilter.setAttribute('aria-expanded', 'true');
      } else {
        searchFilter.classList.remove('wmnds-search-filter--is-open');
        searchFilter.setAttribute('aria-expanded', 'false');
      }
    };

    var clearFilters = function clearFilters() {
      filterOptions.forEach(function(option) {
        option.checked = false; // eslint-disable-line no-param-reassign
      });
      searchFilter.classList.remove('wmnds-search-filter--has-inputs-checked');
    };

    showBtn.addEventListener('click', function(e) {
      e.preventDefault();
      showFilter();
    });
    hideBtn.addEventListener('click', function(e) {
      e.preventDefault();
      showFilter(false);
    });
    document.querySelectorAll('.wmnds-search-filter__clear-all').forEach(function(clearBtn) {
      clearBtn.addEventListener('click', function(e) {
        e.preventDefault();
        clearFilters();
      });
    });
    showResults.addEventListener('click', function() {
      return showFilter(false);
    });
  }
};

var _default = searchFilterJs;
exports["default"] = _default;

Recommended javascript (ES6)
const searchFilterJs = () => {
  const showBtn = document.getElementById('show_filter_btn');
  const hideBtn = document.getElementById('hide_filter_btn');
  const showResults = document.getElementById('show_results_btn');
  const searchFilter = document.getElementById('search_filter');

  if (searchFilter) {
    const filterOptions = searchFilter.querySelectorAll('.wmnds-fe-checkboxes__input');

    filterOptions.forEach(option => {
      option.addEventListener('change', () => {
        if ([...filterOptions].some(input => input.checked)) {
          searchFilter.classList.add('wmnds-search-filter--has-inputs-checked');
        } else {
          searchFilter.classList.remove('wmnds-search-filter--has-inputs-checked');
        }
      });
    });

    const showFilter = (show = true) => {
      if (show) {
        searchFilter.classList.add('wmnds-search-filter--is-open');
        searchFilter.setAttribute('aria-expanded', 'true');
      } else {
        searchFilter.classList.remove('wmnds-search-filter--is-open');
        searchFilter.setAttribute('aria-expanded', 'false');
      }
    };

    const clearFilters = () => {
      filterOptions.forEach(option => {
        option.checked = false; // eslint-disable-line no-param-reassign
      });
      searchFilter.classList.remove('wmnds-search-filter--has-inputs-checked');
    };

    showBtn.addEventListener('click', e => {
      e.preventDefault();
      showFilter();
    });

    hideBtn.addEventListener('click', e => {
      e.preventDefault();
      showFilter(false);
    });

    document.querySelectorAll('.wmnds-search-filter__clear-all').forEach(clearBtn => {
      clearBtn.addEventListener('click', e => {
        e.preventDefault();
        clearFilters();
      });
    });

    showResults.addEventListener('click', () => showFilter(false));
  }
};

export default searchFilterJs;


Search result

What does it do?

  • This is how a matching page will display in the search results page

How it works

  • Each page result will show the page breadcrumbs on desktop. On mobile, breadcrumbs are not shown. This is to reduce page size on smaller devices
  • The page description will display main body copy which is highest on the page. The description will be a maximum of 150 characters. Any descriptions longer than 150 characters will be truncated.
  • If the user’s search query is in the page description, it will be highlighted in bold. This is to help them understand the context of the page
  • The horizontal rule at the bottom of a search result is to make the results list easier to scan.

Swift: The smarter way to travel

Swift is the easy and flexible way to travel around the West Midlands. find the swift card for you. How do you travel? bus…


HTML markup
<div class="wmnds-search-result">
  <h2 class="wmnds-m-b-none"><a href="#" class="h2 wmnds-search-result__title">Swift: The smarter way to travel</a></h2>
  <nav aria-label="Main example breadcrumbs" class="wmnds-breadcrumb wmnds-breadcrumb--mobile-app">
    <ol class="wmnds-breadcrumb__list">
      <li class="wmnds-breadcrumb__list-item">
        <a href="/" class="wmnds-breadcrumb__link">
          Home
        </a>
      </li>
      <li class="wmnds-breadcrumb__list-item">
        <a href="#" class="wmnds-breadcrumb__link">
          Swift and Tickets
        </a>
      </li>
      <li class="wmnds-breadcrumb__list-item">
        <a href="#" class="wmnds-breadcrumb__link wmnds-breadcrumb__link--current" aria-current="page">
          Swift
        </a>
      </li>
    </ol>
  </nav>
  <p class="wmnds-search-result__excerpt"><strong>Swift</strong> is the easy and flexible way to travel around the West Midlands. find the <strong>swift</strong> card for you. How do you travel? bus…</p>
</div>


Pagination links

What does it do?

  • Allows the user to navigate through search results.


HTML markup
<div class="wmnds-pagination">
  <ol class="wmnds-pagination__nav">
    <li class="wmnds-pagination__item wmnds-pagination__item--active">
      1
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">2</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">3</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">4</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">5</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">6</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">7</a>
    </li>
    <li class="wmnds-pagination__item">
      <a class="wmnds-link" href="#">8</a>
    </li>
  </ol>
  <a href="#" target="_self" class="wmnds-pagination__next wmnds-link wmnds-link--with-chevron">
    Next page <svg class="wmnds-link__chevron wmnds-link__chevron--right">
      <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use>
    </svg>
  </a>
</div>

<div class="wmnds-pagination"> <ol class="wmnds-pagination__nav"> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">1</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">2</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">3</a> </li> <li class="wmnds-pagination__item wmnds-pagination__item--previous"> <a class="wmnds-link" href="#">4</a> </li> <li class="wmnds-pagination__item wmnds-pagination__item--active"> 5 </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">6</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">7</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">8</a> </li> </ol> <a href="#" target="_self" class="wmnds-pagination__prev wmnds-link wmnds-link--with-chevron"> <svg class="wmnds-link__chevron wmnds-link__chevron--left"> <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use> </svg> Previous page </a> <a href="#" target="_self" class="wmnds-pagination__next wmnds-link wmnds-link--with-chevron"> Next page <svg class="wmnds-link__chevron wmnds-link__chevron--right"> <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use> </svg> </a> </div>
<div class="wmnds-pagination"> <ol class="wmnds-pagination__nav"> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">1</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">2</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">3</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">4</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">5</a> </li> <li class="wmnds-pagination__item"> <a class="wmnds-link" href="#">6</a> </li> <li class="wmnds-pagination__item wmnds-pagination__item--previous"> <a class="wmnds-link" href="#">7</a> </li> <li class="wmnds-pagination__item wmnds-pagination__item--active"> 8 </li> </ol> <a href="#" target="_self" class="wmnds-pagination__prev wmnds-link wmnds-link--with-chevron"> <svg class="wmnds-link__chevron wmnds-link__chevron--left"> <use xlink:href="#wmnds-general-chevron-right" href="#wmnds-general-chevron-right"></use> </svg> Previous page </a> </div>