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:
- Users need to select from a list of options but might benefit from being able to search or filter the options
- The list of options is long enough that a simple dropdown would be cumbersome
- You need to support both single and multiple selection scenarios
- You want to provide an accessible selection interface that works well with screen readers
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:
- The component's
name
attribute defines the form data name - The
value
property determines what is submitted (as a JSON string array) - The
required
attribute enables built-in validation - The component supports the browser's form validation API
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
- The
required
attribute enforces that at least one option must be selected - The component provides appropriate ARIA attributes for accessibility when invalid
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:
container
: The outer container wrapperlistbox
: The dropdown list containeroption
: Individual option elementscheckbox
: Checkbox element in multiselect modeinput
: The text input fieldarrow
: The dropdown arrow buttonicon
: The slotted icon wrappererror
: The error message containerno-results
: The "No results" message shown when filtering returns no matches
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
- ↑/↓: Navigate through options
- Enter: Select focused option
- Space: Toggle selected state (in multiselect mode)
- Esc: Close dropdown
- Type to filter options
ARIA Implementation
- Uses
role="combobox"
with appropriate ARIA states - Manages
aria-expanded
,aria-selected
, andaria-disabled
states - Supports
aria-invalid
for form validation - Properly labeled through
aria-labelledby
oraria-label
- Form association support
- Comprehensive label management
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
- Always provide a clear label for the ComboBox
- Use meaningful option values and display text
- Consider using multiselect mode only when multiple selections make sense for your use case
- Ensure sufficient contrast for the input and dropdown elements
- Test keyboard navigation and screen reader compatibility
- Use the error slot to provide helpful validation messages
- For complex needs, use the CSS variables and Shadow Parts API for consistent styling