-
Notifications
You must be signed in to change notification settings - Fork 4
Combo Specification
- Overview
- User Stories
- Functionality
- Test Scenarios
- Accessibility
- Assumptions and Limitations
- References
Web Development Team
Developer Name
- Simeon Simeonoff
- Silvia Ivanova
Designer Name
- Vasil Tashkov
- Silvia Ivanova | Date:
- Svilen Dimchevski | Date:
- Radoslav Mirchev | Date: 05-Dec-2022
- Radoslav Karaivanov | Date: 06-Dec-2022
Version | Users | Date | Notes |
---|---|---|---|
1 | Simeon Simeonoff, Vasil Tashkov | 05/12/2022 | Initial spec |
2 | Simeon Simeonoff | 18/01/2023 | Minor updates |
3 | Radoslav Karaivanov | 08/06/2023 | Updated filter options |
4 | Simeon Simeonoff | 20/06/2023 | Updated event details |
5 | Radoslav Karaivanov | 09/01/2024 | Added grouping section |
6 | Radoslav Karaivanov | 10/01/2024 | Dropped items sort when grouping |
7 | Simeon Simeonoff | 25/06/2024 | Updated keyboard navigation related to Enter key behavior |
The Combo component is similar to the Select component in that it provides a list of options from which the user can make a selection. In contrast to the Select component, the Combo component displays all options in a virtualized list of items, meaning the combo box can simultaneously show thousands of options, where one or more options can be selected. Additionally, users can create custom item templates, allowing for robust data visualization. The Combo component features case-sensitive filtering, grouping, complex data binding, dynamic addition of values and more.
End-to-end user experience prototype
Elaborate more on the multi-facetted use cases
Developer stories:
- Story 01: I want to be able to insert a component that allows, upon clicking, the showing of a list of options, so that the users of my app can select item(s) from that list.
- Story 02: I want to be able to easily list all items in a way that separates their underlying value from the displayed option, so that I can separate my model from my view.
- Story 03: I want to be able to initialize the selected value(s) from the list of options, so that I can pre-fill the input with default data.
- Story 04: I want to be able to label the input, so that I can communicate what the expected input value should be.
- Story 05: I want to be able to provide a description or additional text as a secondary label, so that I can communicate what the expected input value should be in greater detail.
- Story 06: I want to be able to provide a placeholder text, so that I can showcase a sample input value or provide a call-to-action message.
- Story 07: I want to be able to show icons at the beginning/end of the component, so that I can communicate the meaning of the input data clearer.
- Story 08: I want to be able to customize the size of the component, so that I can better manage the layout of my app.
- Story 09: I want to be able to see the list of items at all times, regardless of where I place the component in the layout of my app.
- Story 10: I want to be able to customize visual style of the component, so that it can fit the design language of my app.
- Story 11: I want to be able to disable the component, so that I can control the flow of information based on design requirements/constraints.
- Story 12: I want to pad the list of items with a header and/or footer, so that I can provide additional information/functionality in the provided area(s).
- Story 13: I want to bundle the list of options into labeled groups, so that I can control the properties of all items in the group at the same time.
- Story 14: I want to be able to mark the component as required, so that I can enforce the collection of data from the users of my app.
- Story 15: I want to be able to control the validity of the component, so that I can have better control of whether the selected data is valid or not.
- Story 18: I want to be able to use the component in the context of the
<igc-form>
component, so that I can collect its data alongside other inputs. - Story 19: I want to be able to select multiple items from the list of options, so that I can aggregate information as a list of values.
- Story 20: I want to be able to mark the component as read-only, so that users can be informed about a default selection.
- Story 21: I want to be able to provide a collection of values as a data object, so that I don't have to declaratively describe thousands of options in markup.
- Story 22: I want to be able to specify which property in an object should be used as the text value, so that I can separate the actual value from what is displayed to the end user.
- Story 23: I want to be able to specify which property in an object should be used as the data value, so that I can separate the actual value from what is displayed to the end user.
- Story 24: I want to be able to specify which property in an object should be used as the filter value, so that I can filter by value different from what is displayed to the end user.
- Story 25: I want to be able to control how filtering behaves with text containing diacritics/accented symbols and how the component should match them.
- Story 26: I want to be able to select falsy values(0, false, '', null, NaN).
- Story 27: I want to be able to specify a template for individual items, so that I can better customize the end-user experience.
- Story 28: I want to be able to quickly clear the selection made by the end user, so that I can provide a way to start the selection-process anew.
- Story 29: I want to be able to change the UI elements regarding clearing/toggling of the selection, so that I can better customize the end-user experience.
- Story 30: I want to be able to modify the collection of values at runtime, so that I don't have to reinitialize the component every time the data changes.
- Story 31: I want to be able to filter the data of the dropdown at runtime, so that I can provide better end-user experience.
- Story 32: I want to be notified when the value of the input has changed, so that I can react to it in the business logic of my app.
- Story 33: I want to be notified when the dropdown of the input is shown/hidden, so that I can react to it in the business logic of my app.
- Story 34: I want to be notified when the user fires keyboard events inside the input's dropdown, so that I can react to it in the business logic of my app.
- Story 35: I want to show the list of data in a performant way, so that I can present a large set of data for selection to the end-user.
- Story 36: I want to evaluate the validity state of the component, so that I can notify the end-user when a field is required.
A future release will implement the following Developer Story:
- Story 37*: I want to be able to provide a remote collection of values as a data object, so that I don't have to declaratively describe thousands of options in markup.
End-user stories:
- Story 01: I want to be able to select one or more items from a list of options, so that I can fill in an input from a list of pre-defined values.
- Story 02: I want to be able to identify the selected items from the list of options, so that I can know which items are the currently selected one.
- Story 03: I want to be able to navigate and select the list of options using my keyboard and mouse, so that I can use the best input method for me.
- Story 04: I want to be able to filter list of options by a keyword, so that I can limit the number of choices presented to me.
- Story 05: I want to be able to have a clear distinction between selected and unselected items, so that I can make better decisions about my selection.
- Story 06: I want to be able to have a clear distinction between selected and unselected items, so that I can make better decisions about my selection.
- Story 07: I want to be able to easily clear my selection, so that I can quickly restart the selection process.
- Story 08: I want my browser to quickly load the list of options, so that I can quickly start selecting items.
- Story 09: I want to be able to change the search case sensitivity, so that I can better identify the items I'm looking for.
- Story 10: I want to be able to see the text I'm typing when the combo is on focus, so that I am certain of the option I am searching for.
- Story 11: I want to be able to see the list of options upon clearing my selection, so that I can skim over the available options.
Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up
3.1. End-User Experience
** Integration scenarios or functionality with other features/components prototype > ** End-to-end user experienceprototype > ** Prepared design files for styling e.g. interplay with features and light/dark variants design hand-off
3.2. Developer Experience
The following example illustrates how the Combo component can be used in a Lit application.
import { html, render } from 'lit';
const cities = [
{
name: 'London',
id: 'UK01',
region: 'EMEA',
},
{
name: 'Sofia',
id: 'BG01',
region: 'EMEA',
},
];
const combo = document.querySelector('igc-combo');
// Get the item and the visual index(filter-bound);
const itemTemplate = (item) => {
return html`
<div>
<span>${item.name} (${item.id})</span>
</div>
`;
};
// Get the item and the visual index(filter-bound);
const groupHeaderTemplate = (item) => {
return html`
<div>
<span>${item.region}</span>
</div>
`;
};
combo.itemTemplate = itemTemplate;
combo.groupHeaderTemplate = groupHeaderTemplate;
const app = html`
<igc-combo
.data=${cities}
label="Cities"
display-key="name"
value-key="id"
value='["BG01", "BG02"]'
group-key="region"
group-sorting="desc"
autofocus
autofocus-list
placeholder="Pick a city"
placeholder-search="Search for a city"
case-sensitive-icon
disable-filtering
outlined
required
></igc-combo>
`;
render(app);
3.3. Keyboard Navigation
- To trigger any keyboard navigation event, the
<igc-combo>
must be in focus. The list of options can be opened by pressing on any character key, theDown
key, or theAlt + Down
keys, as well as with a mouse click. Using theDown
arrow key will focus(activate) the next item in the list until the end of the list of options is reached, in which case the keyboard navigation will do nothing upon pressing the aforementioned key. TheUp
arrow key will focus(activate) the previous item in the list of options until the beginning of the list is reached. If the user continues pressing on the up key when in the beginning of the list of options, the dropdown closes and the focus returns to the combo input. - While the dropdown menu is open, pressing the
Home
key focuses(activates) the first item in the list of options. Conversely, theEnd
key focuses(activates) the last item in the list of options. While an item is active, pressing theSpace
keys will select/deselect the active item. TheEnter
key selects an item when the combo is single selection mode, but will also close the dropdown menu in all modes. - Pressing the
Esc
key closes the list of options without changing the selection. - When adding custom values is allowed, a new item can be added while the
Add Item
button is on focus by pressing theEnter
key.
Keys | Description |
---|---|
Down / Alt + Down |
Opens the list of options. |
Keys | Description |
---|---|
Down |
Activates the next item from the list of options. |
Up |
Activates the previous item from the list of options. If the first item is already active it will focus the input. |
Space |
Selects the active item. |
Enter |
Selects the active item in single selection mode and closes the list of options in all modes. |
Home |
Activates the first item from the list of options. |
End |
Activates the last item from the list of options. |
Esc |
Closes the list of options. |
Tab / Shift + Tab |
Closes the list of options. |
Keys | Description |
---|---|
Enter |
Adds a new item and returns focus to the input. |
Up |
Returns focus to the input. |
Additional functionality: Typing while the component is in focus will filter the list of items for those that most closely match the current user input.
3.4. Grouping
- When a group key is set, the igc-combo will group its items based on that key.
- Items which cannot be resolved based on the passed group key (that is
T[groupKey]
returningnull
orundefined
) will be aggregated into a group named "Other". - When grouping is enabled, developers may control the sorting directions of the groups through the
groupSorting
property. Defaults to'asc'
(ascending). - The sorting is locale aware.
Name | Description | Type | Default value |
---|---|---|---|
filterKey |
The key in the data source used for filtering the list of items. | keyof T |
Defaults to the combo displayKey . |
caseSensitive |
Whether the filter operations should be case sensitive. | Boolean |
false |
matchDiacritics |
Whether the filter operations should distinguish between accented letters and their base counterparts. | Boolean |
false |
Name | Description | Type | Default value | Reflected |
---|---|---|---|---|
data |
The data source used to render items. | T[] |
- |
false |
value |
Gets/sets the selected items in the combo input. | Values<T>[] |
- |
- |
display-key |
Determines which column in the data source is used as the display value. | Keys<T> |
- |
false |
value-key |
Determines which column in the data source is used as the value. | Keys<T> |
- |
false |
group-key |
The item property by which items should be grouped inside the items list. Not usable if data is not of type Object[]. | Keys<T> |
- |
false |
group-sorting |
Sets the sorting direction for the groups. | asc | desc | none |
asc |
false |
single-select |
Disables multi-item selection and moves filtering prompt to the main input. | Boolean |
false |
true |
filtering-options |
Allows passing configuration of filterKey , caseSensitivity . |
FilteringOptions |
- |
false |
disable-filtering |
Disables the filtering of the list of options. Has no effect when single-select is set. |
Boolean |
false |
false |
case-sensitive-icon |
Allows case-sensitive search to be controlled by the end-user. Has no effect when single-select is set. |
Boolean |
false |
true |
open |
Opens the list of items by default. | Boolean |
false |
false |
autofocus |
Automatically focuses the component on page load. | Boolean |
false |
false |
autofocus-list |
The list of options gets focused upon opening. Has no effect when single-select is set. |
Boolean |
false |
false |
name |
Sets the name of the component. | string |
- |
false |
label |
Sets the label of the component. | string |
- |
false |
placeholder |
Sets the placeholder of the component. | string |
- |
false |
placeholder-search |
Sets the placeholder of the input in the dropdown menu. Has no effect when single-select is set. |
string |
- |
false |
outlined |
Sets material-themed inputs to outlined style mode. | Boolean |
false |
true |
disabled |
Sets the disabled state of the component. | Boolean |
false |
true |
required |
Sets the required state of the component. | Boolean |
false |
true |
invalid |
Sets the validity of the component. | Boolean |
false |
true |
Scheduled for implementation:
Name | Description | Type | Default value | Reflected |
---|---|---|---|---|
custom-values |
Allows the users to add own values to the list of data. | Boolean | false |
false |
Name | Description | Return type | Parameters |
---|---|---|---|
toggle |
Toggles the list of options. | void |
- |
show |
Shows the list of options. | void |
- |
hide |
Hides the list of options. | void |
- |
focus |
Focuses the component. | - |
options: FocusOptions |
blur |
Blurs the component. | void |
- |
select |
Selects the defined items. If items is an empty array, all items are selected. | void |
items?: <T>[] |
deselect |
Deselects the defined items. If items is an empty array, all items are deselected. | void |
items?: <T>[] |
checkValidity |
Marks the component as invalid if it doesn't satisfy the validation constraints. | boolean |
- |
reportValidity |
Returns true if the component satisfies the validation constraints. | boolean |
- |
itemTemplate |
The custom template, if any, that should be used when rendering items in list of options. | TemplateResult |
value<T> |
groupHeaderTemplate |
The custom template, if any, that should be used when rendering header items in list of options. | TemplateResult |
value<T> |
selection |
Gets the current value/selection as array of objects. | <T>[] |
- |
Scheduled for implementation:
Name | Description | Return type | Parameters |
---|---|---|---|
filterFunction |
Gets/sets the custom filtering function used for the combo. The passed function can be async . |
Function |
collection: T[], searchValue: any, options: FilteringOptions |
navigateTo |
Navigates to the item with specified value. | IgcSelectItem |
value<T> |
Name | Description | Cancelable | Parameters |
---|---|---|---|
igcFocus |
Emitted when the component gains focus. | false |
|
igcBlur |
Emitted when the component loses focus. | false |
|
igcOpening |
Emitted before the list of options is opening. | true |
|
igcOpened |
Emitted after the list of options is opened. | false |
|
igcClosing |
Emitted before the dropdown is closing. | true |
|
igcClosed |
Emitted after the list of options is closed. | false |
|
igcChange |
Emitted after selection is done on blur. | true |
{newValue: string[], items: T[], type: 'selection' | 'deselection' | 'addition' }
|
Scheduled for implementation:
Name | Description | Cancelable | Parameters |
---|---|---|---|
igcNewCustomValue |
Emitted when an item is being added to the data collection. | true |
{oldCollection, itemAdded, newCollection} |
igcFiltering |
Emitted when the list is being filtered. | true |
{searchTerm} |
igcFiltered |
Emitted when the list is filtered. | false |
{searchTerm, newCollection} |
The <igc-combo>
component provides the following CSS parts:
Name | Description |
---|---|
label |
The encapsulated text label. |
input |
The main input field. |
native-input |
The native input of the main input field. |
prefix |
The prefix wrapper. |
suffix |
The suffix wrapper. |
toggle-icon |
A toggle icon wrapper. |
clear-icon |
A clear icon wrapper. |
case-icon |
A case-icon wrapper that renders content inside the suffix of the filter-input. |
helper-text |
A helper-text wrapper that renders content below the target input. |
search-input |
The search input field. |
list-wrapper |
A list-wrapper that holds the filter-input and the igc-combo-list component. |
list |
The list of options (igc-combo-list). |
item |
An item-wrapper that holds the content of the combo items. |
group-header |
A wrapper that holds the text content of the group headers. |
active |
A wrapper that holds the content of the combo active items. |
selected |
A wrapper that holds the content of the combo selected items. |
checkbox |
Represents each checkbox of each list item. |
checkbox-indicator |
Represents the checkbox indicator of each list item. |
checked |
Appended to checkbox parts list when checkbox is checked. |
empty |
The container holding the empty template. |
The <igc-combo>
component provides the following slots:
Name | Description |
---|---|
header |
Renders the header element. |
footer |
Renders the footer element. |
prefix |
Renders the prefix element. |
suffix |
Renders the suffix element. |
helper-text |
Renders the helper-text element. |
toggle-icon |
Renders the toggle-icon element. |
clear-icon |
Renders the clear-icon element. |
empty |
Renders when no items are shown in the dropdown. |
Scheduled for implementation:
Name | Description |
---|---|
add-item |
Renders the Add Button UI in the dropdown. |
loading |
Renders the loading container. |
The <igc-combo-item>
component provides the following slots:
Name | Description |
---|---|
(default) | Renders the item's content. |
The <igc-combo-header>
component provides the following slots:
Name | Description |
---|---|
(default) | Renders the header's content. |
ARIA Support
-
<igc-combo>
- rolecombobox
.-
aria-owns
-encapsulated container holding all items
. aria-haspopup
-
aria-describedby
-helper-text
. -
aria-disabled
- set to the disabled attribute of the component.
-
-
<igc-combo-item>
(implicit)-
role
-option
. -
aria-selected
- depends on its selection status.
-
-
<igc-select-group>
(implicit)-
role
-group
-
- encapsulated container holding all items - role="listbox"
RTL Support The component should provide full RTL support by default.
Assumptions | Limitation Notes |
---|---|
Specify all referenced external sources