Provides a compact UI element used either to represent a filter or to recommend an option.

You can find here the OUDS chip design guidelines.

Overview

Component types

  • Filter chip is a filter option that can be selected or deselected by the user.
  • Suggestion chip is a recommended or predictive option based on user input or context.

Approach

Chip components are always displayed in a containing list with a ul.chip-container class as they are always displayed as a group. This can be adapted to your needs and context of use.

.chip-container manages the overall chip list layout.

.chip is the main class defining the chip component. It controls the placement inside the container and the click area.

.chip-interactive is the element that carries the interactive part of the component.

Accessibility

Visually impaired and blind users will lack the visual context that permits to understand the chips list purpose on the page especially if chips' labels are not self-explanatory. Thus it's mandatory to add a semantically informative title to describe the chips' list purpose if possible, otherwise an aria-label on the containing ul must be added. To improve accessibility and denote the chips' list uniqueness of purpose, it's possible to add role=group on a parent container (but not the ul as it would not work).

Several examples are provided below but they will need to be adapted for actual use cases.

Pseudo elements

Here is a table summarizing the pseudo elements that are used by the different variants of the chip.

chip variant.chip-interactive::before.chip-interactive::after
Filter chipUsedUsed
Suggestion chipUsed

Filter chip

Filter chips allow users to filter content by selecting or deselecting specific categories or attributes while keeping the element on the page. They are based on checkbox inputs, but we also have button based or radio button based filter chips. Thus, there is a selected state on this variant of the component.

To create a filter chip, add .chip-filter to the .chip.

If possible, display a semantically informative title to describe the chips' list purpose like in the following example, otherwise an aria-label must be added to the .chip-container to explain the function of the chips, more information here.

Filter by brands


<h4 id="filtersHeader">Filter by brands</h4>
<div role="group" aria-labelledby="filtersHeader">
  <ul class="chip-container">
    <li class="chip chip-filter">
      <input type="checkbox" id="appleCheck" checked />
      <label class="chip-interactive" for="appleCheck">
        Apple
      </label>
    </li>
    <li class="chip chip-filter">
      <input type="checkbox" id="samsungCheck" />
      <label class="chip-interactive" for="samsungCheck">
        Samsung
      </label>
    </li>
    <li class="chip chip-filter">
      <input type="checkbox" id="xiaomiCheck" />
      <label class="chip-interactive" for="xiaomiCheck">
        Xiaomi
      </label>
    </li>
  </ul>
</div>
html

Technical implementation

Using radio buttons

To have only one active filter chip at a time, use the radio button version. All the rules explained in this page about filter chips apply on this variant as well.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <input type="radio" id="radioCheck" name="radio" />
    <label class="chip-interactive" for="radioCheck">
      Filter with radio 1
    </label>
  </li>
  <li class="chip chip-filter">
    <input type="radio" id="radioCheck2" name="radio" />
    <label class="chip-interactive" for="radioCheck2">
      Filter with radio 2
    </label>
  </li>
  <li class="chip chip-filter">
    <input type="radio" id="radioCheck3" name="radio" checked />
    <label class="chip-interactive" for="radioCheck3">
      Filter with radio 3
    </label>
  </li>
</ul>
html

Using buttons

If you need to trigger a dynamic interaction directly on the page, <button> markup is also supported. All the rules explained in this page about filter chips apply on this variant as well.

The style is applied on [aria-pressed="true"] to enforce a good level of accessibility.

Make use of our button JS plugin or handle interactivity on your side, but make sure to use aria-pressed.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Filter label using button 1
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Filter label using button 2
    </button>
  </li>
</ul>
html
Button plugin

The button plugin allows you to create simple on/off toggle buttons.

Toggle states

Add data-bs-toggle="button" to toggle a button’s active state. If you’re pre-toggling a button, you must manually add the .active class and aria-pressed="true" to ensure that it is conveyed appropriately to assistive technologies.

Methods

You can create a button instance with the button constructor, for example:

const bsButton = new oudsWeb.Button('#myButton')
MethodDescription
disposeDestroys an element’s button. (Removes stored data on the DOM element)
getInstanceStatic method which allows you to get the button instance associated with a DOM element, you can use it like this: oudsWeb.Button.getInstance(element).
getOrCreateInstanceStatic method which returns a button instance associated with a DOM element or creates a new one in case it wasn’t initialized. You can use it like this: oudsWeb.Button.getOrCreateInstance(element).
toggleToggles push state. Gives the button the appearance that it has been activated.

For example, to toggle all chips:

document.querySelectorAll('.chip-suggestion').forEach(chipElement => {
  const chip = oudsWeb.Button.getOrCreateInstance(chipElement)
  chip.toggle()
})

Variants

Text and icon

To display an icon add the icon as the last child of the .chip-interactive.

The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <input type="checkbox" id="filterWithIcon" />
    <label class="chip-interactive" for="filterWithIcon">
      Filter with icon
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
    </label>
  </li>
  <li class="chip chip-filter">
    <input type="checkbox" id="filterWithIcon2" checked />
    <label class="chip-interactive" for="filterWithIcon2">
      Another filter with icon
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
    </label>
  </li>
</ul>
html

Icon only

To display a chip with only an icon, add .chip-icon to the interactive part of the component.

The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.

Make sure to provide an accessible text for each chip.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <input type="checkbox" id="filterIconOnly1" />
    <label class="chip-interactive chip-icon" for="filterIconOnly1">
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
      <span class="visually-hidden">Favorites</span>
    </label>
  </li>
  <li class="chip chip-filter">
    <input type="checkbox" id="filterIconOnly2" checked />
    <label class="chip-interactive chip-icon" for="filterIconOnly2">
      <span class="icon si si-settings" aria-hidden="true"></span>
      <span class="visually-hidden">Technical</span>
    </label>
  </li>
</ul>
html

States

Disabled state

Add disabled attribute either on the input or on the button element to disable the chip.

The following example shows every possible renderings depending on the filter chip type but it is not recommended to mix different types in a real use case.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <input type="checkbox" id="disabledFilter" checked disabled />
    <label class="chip-interactive" for="disabledFilter">
      Disabled checked filter
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
    </label>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button" disabled>
      Disabled unchecked filter
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
    </button>
  </li>
</ul>
html

Suggestion chip

Suggestion chips show relevant options based on user input or context. They help users quickly choose from dynamic or recommended items. Since this implies a dynamic behavior, these should be implemented using buttons.

To create a suggestion chip, add .chip-suggestion to the .chip.

If possible, display a semantically informative title to describe the chips' list purpose, otherwise an aria-label must be added to the .chip-container to explain the function of the chips, like in the following example. More information here.

<ul class="chip-container" aria-label="Answer with">
  <li class="chip chip-suggestion">
    <button class="chip-interactive">
      Thanks.
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive">
      Looks good to me.
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive">
      Can we talk about it later ?
    </button>
  </li>
</ul>
html

Variants

Text and icon

To display an icon, add the icon as the first child of the .chip-interactive.

The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.

<ul class="chip-container" aria-label="Answer with">
  <li class="chip chip-suggestion">
    <button class="chip-interactive">
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
      Suggestion with icon 1
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive">
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
      Suggestion with icon 2
    </button>
  </li>
</ul>
html

Icon only

To display a chip with only an icon, add .chip-icon to the <button>.

The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.

Make sure to provide an accessible text for each chip.

<ul class="chip-container" aria-label="Answer with">
  <li class="chip chip-suggestion">
    <button class="chip-interactive chip-icon">
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
      <span class="visually-hidden">I love it.</span>
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive chip-icon">
      <span class="icon si si-settings" aria-hidden="true"></span>
      <span class="visually-hidden">Go to parameters.</span>
    </button>
  </li>
</ul>
html

States

Disabled state

Add disabled attribute on the button element to disable the chip.

The following example shows every possible renderings depending on the suggestion chip type but it is not recommended to mix different types in a real use case.

<ul class="chip-container" aria-label="Answer with">
  <li class="chip chip-suggestion">
    <button class="chip-interactive" disabled>
      Thanks.
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive" disabled>
      <svg aria-hidden="true">
        <use xlink:href="/orange/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
      </svg>
      Suggestion with icon 1
    </button>
  </li>
  <li class="chip chip-suggestion">
    <button class="chip-interactive chip-icon" disabled>
      <span class="icon si si-settings" aria-hidden="true"></span>
      <span class="visually-hidden">Send "Go to parameters."</span>
    </button>
  </li>
</ul>
html

Layout

This part explains global truth among all the chip variants.

Overflowing

By default when using .chip-container the chip list will scroll horizontally on one line.

<ul class="chip-container" aria-label="Filter by">
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
</ul>
html

Wrapping

Add .flex-wrap on the .chip-container element to display a wrapping list of chips. Beware with this option as it could take too much vertical space on mobile viewports, as a rule there should not be more than 2 or 3 lines of chips displayed.

<ul class="chip-container flex-wrap" aria-label="Filter by">
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
</ul>
html

Mix of both

For some use cases, mixing wrapping and overflowing can lead to a better UX.

This layout combines wrapping and vertical scrolling, please note that a style="max-height: 115px;" is added since we don’t want to display more than 2 or 3 lines, and still show part of the following line as a visual clue when the scrollbar is not displayed.

<ul class="chip-container flex-wrap" style="max-height: 115px;" aria-label="Filter by">
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive active" aria-pressed="true" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
  <li class="chip chip-filter">
    <button class="chip-interactive" data-bs-toggle="button">
      Quite long label
    </button>
  </li>
</ul>
html