ComboBox

Component status

Status
Is the design finished and component available in Figma library? Missing
Is the design documentation complete? Missing
Is the technical documentation complete? Up to date

Introduction

The ComboBox component combines a text input with a dropdown selection, offering users a flexible way to select one or multiple options from a list. It supports both keyboard and mouse interactions, with built-in filtering capabilities to help users quickly find their desired options.

When to use

Use the ComboBox component when:

Implementation

The ComboBox is implemented as a Web Component following the WAI-ARIA Authoring Practices Guide. Import it using:

<script type="module" src="https://cdn.design-system.triptease.io/tt-combobox/latest/tt-combobox.js"></script>

Variants

Single Selection

The default mode allows users to select a single option from the list.

<tt-combobox id="single-combobox">
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option">Option 2</option>
    <option value="3" slot="option">Option 3</option>
</tt-combobox>

Multiple Selection

Enable multiple selection using the multiselect attribute. Add display-select-all to show a "Select all" option.

<tt-combobox id="multi-combobox" multiselect display-select-all>
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option">Option 2</option>
    <option value="3" slot="option">Option 3</option>
</tt-combobox>

Disabled State

Disable the entire combobox:

<tt-combobox id="disabled-combobox" disabled>
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option">Option 2</option>
    <option value="3" slot="option">Option 3</option>
</tt-combobox>

Or disable individual options:

<tt-combobox id="individual-disabled-combobox">
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option" disabled>Option 2</option>
    <option value="3" slot="option">Option 3</option>
</tt-combobox>

Attributes

Attribute Type Default Description
multiselect boolean false Enables selection of multiple options
disabled boolean false Disables all interaction with the component
value string[] [] Array of selected option values (e.g., value='["1","2"]')
display-select-all boolean false Shows a "Select all" option in multiselect mode
name string "" Name attribute for the form input element
aria-labelledby string "" ID of the element that labels this combobox
required boolean false Makes the combobox a required field in forms
invalid boolean false Manually marks the combobox as invalid
hide-caret boolean false Hides the text cursor in the input field

Slots

The ComboBox component provides the following slots:

Slot Name Description
option Used for adding option elements to the combobox
error Used for custom error messages that appear when validation fails
icon Used for adding an icon that appears before the input field

Option Slot

The option slot accepts <option> elements just like a native <select>:

<tt-combobox id="example-combobox">
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option" disabled>Option 2 (Disabled)</option>
  <option value="3" slot="option">Option 3</option>
</tt-combobox>

Error Slot

The error slot allows you to provide custom error messages for validation:

<tt-combobox id="required-combobox" required>
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option">Option 2</option>
  <span slot="error">This field is required. Please select an option.</span>
</tt-combobox>

The error message is only visible when the combobox is invalid.

Icon Slot

The icon slot allows you to add an icon before the input field:

<tt-combobox id="icon-combobox">
  <svg slot="icon" width="16" height="16" viewBox="0 0 16 16">
    <!-- Icon SVG content -->
  </svg>
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option">Option 2</option>
</tt-combobox>

Events

The ComboBox component fires the following events:

Event Name Description Event Detail
change Fired when the selection changes N/A

Example usage:

const combobox = document.querySelector('#my-combobox');
combobox.addEventListener('change', () => {
  console.log('Selected values:', combobox.value);
});

Form Integration

The ComboBox component is form-associated, meaning it can be used within <form> elements and participates in form submission and validation.

When used within a form:

Example form usage:

<form id="my-form">
  <label for="my-combobox">Select options:</label>
  <tt-combobox id="my-combobox" name="options" required>
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option">Option 2</option>
    <span slot="error">Please select at least one option</span>
  </tt-combobox>
  <button type="submit">Submit</button>
</form>

The form will submit the ComboBox value as a JSON array, e.g., options=["1","2"].

Validation

The ComboBox component integrates with the browser's form validation system and provides visual feedback for invalid states.

Built-in Validation

Manual Validation

You can manually set the invalid state using the invalid attribute:

<tt-combobox id="invalid-combobox" invalid>
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option">Option 2</option>
  <span slot="error">This combobox is marked as invalid</span>
</tt-combobox>

Custom Error Messages

Use the error slot to provide custom error messages:

<tt-combobox id="required-combobox" required>
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option">Option 2</option>
  <span slot="error">Please select an option from the list</span>
</tt-combobox>

The error message is only displayed when the combobox is in an invalid state.

Styling

The component uses Shadow DOM and exposes the following parts for styling using the Shadow Parts API:

Example styling:

tt-combobox::part(container) {
    border: 1px solid var(--color-tertiary-400);
    background-color: var(--color-surface-500);
    border-radius: 18px;
}

tt-combobox::part(listbox) {
    background-color: var(--color-surface-500);
    border: 1px solid var(--color-tertiary-400);
    border-radius: 8px;
}

CSS Variables

The component respects the following CSS variables for styling:

Variable Default Description
--tt-combobox-flex-direction row Direction of the component layout
--tt-combobox-align-items center Alignment of items in the component
--tt-combobox-justify-content initial Justification of items in the component
--tt-combobox-align-content initial Alignment of content in the component
--tt-combobox-gap 0.5rem Gap between component elements
--tt-combobox-font-size var(--font-size-200) Font size for the component
--tt-combobox-color var(--color-text-400) Text color for the component
--tt-combobox-max-width 300px Maximum width of the combobox
--tt-combobox-min-width 250px Minimum width of the combobox
--tt-combobox-border-color var(--color-border-400) Border color of the combobox
--tt-combobox-border-width 1px Border width of the combobox
--tt-combobox-background-color var(--color-surface-100) Background color of the combobox
--tt-combobox-hover-background-color var(--color-surface-300) Background color on hover
--tt-combobox-placeholder-color var(--color-text-300) Color of placeholder text
--tt-combobox-dropdown-color var(--color-text-400) Color of dropdown arrow
--tt-combobox-icon-size 1rem Size of the icon
--tt-combobox-list-max-width 35ch Maximum width of dropdown list
--tt-combobox-max-height 400px Maximum height of dropdown list
--tt-combobox-top calc(100% + 0.5rem) Top position of dropdown
--tt-combobox-left 0 Left position of dropdown
--tt-combobox-right unset Right position of dropdown
--tt-combobox-bottom unset Bottom position of dropdown
--tt-combobox-label-font-size inherit Font size of the label
--tt-combobox-label-color inherit Color of the label
--tt-combobox-label-font-weight inherit Font weight of the label
--tt-combobox-disabled-border-color var(--color-border-200) Border color when disabled
--tt-combobox-disabled-color var(--color-text-200) Text color when disabled
--tt-combobox-disabled-background-color var(--color-surface-200) Background color when disabled
--tt-combobox-disabled-placeholder-color var(--color-text-200) Placeholder color when disabled

Example of setting CSS variables:

tt-combobox {
  --tt-combobox-max-width: 400px;
  --tt-combobox-border-color: var(--color-primary-300);
  --tt-combobox-background-color: var(--color-surface-200);
}

Individual Option Styling

To style specific options, wrap the option text in a span and apply styles directly:

<tt-combobox id="individual-styled-combobox">
    <option value="1" slot="option">Option 1</option>
    <option value="2" slot="option">
        <span style="background-color: var(--color-tertiary-100); font-family: var(--font-family-serif)">
            Option 2
        </span>
    </option>
    <option value="3" slot="option">Option 3</option>
</tt-combobox>

Accessibility

Keyboard Support

ARIA Implementation

Advanced Examples

ComboBox with Icon and Custom Styling

<style>
  #custom-combobox {
    --tt-combobox-border-color: var(--color-primary-400);
    --tt-combobox-border-width: 2px;
    --tt-combobox-background-color: var(--color-surface-200);
    --tt-combobox-icon-size: 1.25rem;
  }
  
  #custom-combobox::part(container) {
    border-radius: 18px;
    padding: 0.75rem;
  }
  
  #custom-combobox::part(listbox) {
    border-radius: 12px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  }
</style>

<tt-combobox id="custom-combobox">
  <svg slot="icon" width="16" height="16" viewBox="0 0 16 16">
    <!-- SVG content here -->
  </svg>
  <option value="1" slot="option">Option 1</option>
  <option value="2" slot="option">Option 2</option>
  <option value="3" slot="option">Option 3</option>
</tt-combobox>

Form Integration with Validation

<form id="survey-form">
  <label for="interests">Select your interests:</label>
  <tt-combobox id="interests" name="user_interests" multiselect required>
    <option value="tech" slot="option">Technology</option>
    <option value="art" slot="option">Art & Design</option>
    <option value="science" slot="option">Science</option>
    <option value="music" slot="option">Music</option>
    <option value="sports" slot="option">Sports</option>
    <span slot="error">Please select at least one interest</span>
  </tt-combobox>
  
  <button type="submit">Submit</button>
</form>

<script>
  const form = document.getElementById('survey-form');
  const combobox = document.getElementById('interests');
  
  form.addEventListener('submit', (event) => {
    event.preventDefault();
    
    if (form.checkValidity()) {
      console.log('Form submitted with interests:', combobox.value);
      // Submit the form...
    }
  });
</script>

Best Practices