Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
97728bc
fix(combo): keep the inner events of the search input and the list in…
rkaraivanov Oct 27, 2026
6fd035f
fix(combo): move Tab through the focusable content of the list slots
rkaraivanov Oct 27, 2026
32501bd
feat(combo): report the trigger that closes the list
rkaraivanov Oct 27, 2026
fe4aad4
feat(combo): add the primitives for remote data
rkaraivanov Oct 27, 2026
11eb521
feat(extras): add bindComboDataSource
rkaraivanov Oct 27, 2026
783b44a
feat(combo): add selectAllItems and deselectAllItems
rkaraivanov Oct 27, 2026
e533746
chore(deps): update igniteui-i18n-core and igniteui-i18n-resources to…
rkaraivanov Oct 27, 2026
e30b992
feat(combo): add totalItemCount and loading
rkaraivanov Oct 27, 2026
2f87390
feat(extras): set totalItemCount and loading from bindComboDataSource
rkaraivanov Oct 27, 2026
16b528d
feat(combo): add the select-all option
rkaraivanov Oct 27, 2026
6167fae
fix(combo): show loading as a spinner in the input and placeholders a…
rkaraivanov Oct 27, 2026
824517b
docs(stories): show the remote, loading, select-all and staged select…
rkaraivanov Oct 27, 2026
b0a7a92
fix(combo): give igcChange newValue the order of the value that follows
rkaraivanov Oct 27, 2026
5ca92fa
feat(combo): add group selection
rkaraivanov Oct 27, 2026
6f93906
docs(stories): show the group selection of the combo
rkaraivanov Oct 27, 2026
d55bae7
feat(combo): add a confirm mode for the selection
rkaraivanov Oct 27, 2026
8fda147
feat(combo): add Cancel and Apply buttons to the confirm mode
rkaraivanov Oct 27, 2026
577b28f
refactor(combo): show loading with igc-circular-progress
rkaraivanov Oct 27, 2026
b134496
"docs(stories): show the confirm mode of the combo
rkaraivanov Oct 27, 2026
6974aa2
refactor(combo): move the igcDataRequest paging to ComboDataRequests
rkaraivanov Oct 27, 2026
a498566
refactor(combo): move the toggle option ranges to DataState
rkaraivanov Oct 27, 2026
4ac4689
refactor(combo): move the selection state to ComboSelection
rkaraivanov Oct 28, 2026
3555912
refactor(combo): tidy the regions of combo.ts
rkaraivanov Oct 28, 2026
04cccd0
test(combo): split combo.spec.ts into four files
rkaraivanov Oct 28, 2026
fff871b
docs(combo): consolidate the specification in STE
rkaraivanov Oct 28, 2026
824e414
Merge branch 'master' into rkaraivanov/combo-enhancements
rkaraivanov Oct 28, 2026
b9310ce
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Oct 30, 2026
5015e34
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 6, 2026
8267206
feat(combo): show the case-sensitive icon in remote mode
rkaraivanov Nov 6, 2026
6bd45c7
feat(combo): indent the items under group header options
rkaraivanov Nov 6, 2026
f6ed20f
fix(circular-progress): respect reduced motion and forced colors
rkaraivanov Nov 6, 2026
fea5683
fix(linear-progress): respect reduced motion
rkaraivanov Nov 6, 2026
9553909
feat(combo): report aria-checked in multiple selection
rkaraivanov Nov 6, 2026
a78208a
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 6, 2026
3f40217
fix(combo, pickers): honor handled Escape; reuse shared Tab helpers
rkaraivanov Nov 6, 2026
e3a2ad1
Merge branch 'master' into rkaraivanov/combo-enhancements
ChronosSF Nov 10, 2026
a99850a
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 11, 2026
dc59c5c
fix(combo): address PR #2545 review; shared IME guard
rkaraivanov Nov 11, 2026
33a8dc0
Merge branch 'rkaraivanov/combo-enhancements' of https://github.com/I…
rkaraivanov Nov 11, 2026
84d2c0b
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 11, 2026
9e6ab0e
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 12, 2026
15b40c4
Merge remote-tracking branch 'origin/master' into rkaraivanov/combo-e…
rkaraivanov Nov 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .agents/context/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Read them before making changes; if they disagree with this file, they win.
- `src/internals/`, `src/theming/`, `src/animations/`: shared code, imported only through the
`#internals/*`, `#theming/*` and `#animations/*` aliases. The theme aggregator of a component
is imported through `#themes/*`.
- `src/extras/`: opt-in add-ons, published as `igniteui-webcomponents/extras`
- `src/extras/`: opt-in add-ons, published under `igniteui-webcomponents/extras`. A new add-on gets its own
subpath export, so an import pulls in only its own dependencies
- `src/styles/`: global SCSS utilities, mixins and themes
- `src/index.ts`: the public entry point of the package
- `stories/`: Storybook stories, one per component tag
Expand Down
2 changes: 1 addition & 1 deletion .github/CODING_GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
src/
├── animations/ # Animation players and presets → #animations/*
├── components/ # One directory per component, each with its own spec.md
├── extras/ # Opt-in add-ons, published as `igniteui-webcomponents/extras`
├── extras/ # Opt-in add-ons, published under `igniteui-webcomponents/extras`
├── internals/ # Shared building blocks, never public API → #internals/*
├── styles/ # Global SCSS: utilities, mixins, themes
├── theming/ # Theming controller and types → #theming/*
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Dock Manager - EXCLUSIVE FEATURE](#dock-manager---exclusive-feature)
- [Quick start](#quick-start)
- [Bundling a single theme](#bundling-a-single-theme)
- [Extras](#extras)
- [Browser support](#browser-support)
- [Tooling](#tooling)
- [Editor metadata](#editor-metadata)
Expand Down Expand Up @@ -184,6 +185,28 @@ The condition names are `igc-theme-material`, `igc-theme-bootstrap`, `igc-theme-
- Load the global theme style sheet as before, for example `igniteui-webcomponents/themes/light/bootstrap.css`.
- Without a condition, the bundle contains all four themes, as before.

## Extras

The extras are opt-in add-ons that build on the public API of the components. A bundle that does not import them does not contain them. Each one has its own entry point, so it needs only its own dependencies.

- `createMarkdownRenderer()` from `igniteui-webcomponents/extras` renders the chat messages from Markdown, with syntax highlighting. It imports the optional peer dependencies `marked` and `dompurify`, and loads `shiki` for the highlighting.
- `bindComboDataSource()` from `igniteui-webcomponents/extras/combo-data-source` binds a combo to a server that searches and pages. It sets `totalItemCount` from the total of the server, so the list shows a placeholder row for each item to load, and `loading` while a search waits or a page loads.

```ts
import { bindComboDataSource } from 'igniteui-webcomponents/extras/combo-data-source';

const binding = bindComboDataSource(combo, {
load: async ({ searchText, caseSensitive, startIndex, count }, signal) => {
const query = `q=${encodeURIComponent(searchText)}&case=${caseSensitive}&skip=${startIndex}&top=${count}`;
const response = await fetch(`/api/cities?${query}`, { signal });
const { items, total } = await response.json();
return { items, totalCount: total };
},
});

binding.dispose(); // removes the listeners, aborts the request in flight and clears `totalItemCount` and `loading`
```

## Browser support

| ![chrome_48x48] | ![firefox_48x48] | ![edge_48x48] | ![opera_48x48] | ![safari_48x48] |
Expand Down
74 changes: 64 additions & 10 deletions api-reference/igc-combo.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defineComponents(IgcComboComponent);
## Properties

- `data`: `T[]`. Default: `[]`. No attribute.
The data source used to generate the list of options.
The data source used to generate the list of options. A new data source
keeps the selection, also the selected items that it does not hold.
- `outlined`: `boolean`. Default: `false`. Attribute: `outlined`, reflected.
Whether the control has an outlined appearance.
- `singleSelect`: `boolean`. Default: `false`. Attribute: `single-select`, reflected.
Expand Down Expand Up @@ -44,12 +45,34 @@ defineComponents(IgcComboComponent);
An object that configures the filtering of the combo.
- `caseSensitiveIcon`: `boolean`. Default: `false`. Attribute: `case-sensitive-icon`.
Whether the search input shows the icon that toggles case-sensitive
filtering.
filtering. In remote filtering mode, read `filteringOptions.caseSensitive`
when you send the search to the server.
- `disableFiltering`: `boolean`. Default: `false`. Attribute: `disable-filtering`.
Whether the filtering of the list of options is disabled. In multiple
selection mode, it also hides the search input.
- `disableClear`: `boolean`. Default: `false`. Attribute: `disable-clear`.
Whether the clear button is hidden.
- `totalItemCount`: `number | undefined`. Attribute: `total-item-count`.
The number of all the items of a remote source, when the source knows it.
In remote filtering mode, the list shows a placeholder for each item that
`data` does not hold yet, so the scrollbar shows the full list.
- `loading`: `boolean`. Default: `false`. Attribute: `loading`, reflected.
Whether the combo loads options. A spinner, which the `loading` slot can
replace, then takes the place of the toggle icon, and an empty list shows
a loading message instead of the empty message.
- `showSelectAll`: `boolean`. Default: `false`. Attribute: `show-select-all`.
Whether the list starts with an option that selects all the items that it
shows, or deselects them when all of them are selected. Only in multiple
selection mode.
- `groupSelection`: `boolean`. Default: `false`. Attribute: `group-selection`.
Whether a group header is an option that selects the items of its group
that the list shows, or deselects them when all of them are selected.
Only in multiple selection mode with `groupKey`.
- `selectionCommit`: `'immediate' | 'confirm'`. Default: `'immediate'`. Attribute: `selection-commit`.
When the user's changes of the selection apply in multiple selection
mode. With `confirm`, they change a pending selection while the list is
open, and Enter or the Apply button applies it with one `igcChange`. Any
other close drops it. While it exists, the selection methods change it too.
- `itemTemplate`: `ComboItemTemplate<T>`. No attribute.
The template used for the content of each combo item.
- `groupHeaderTemplate`: `ComboGroupHeaderTemplate<T>`. No attribute.
Expand All @@ -59,6 +82,10 @@ defineComponents(IgcComboComponent);
field of an item. Without it, each value is the item itself.
- `selection`: `T[]`. Read-only. No attribute.
Returns the current selection as an array of objects as provided in the `data` source.
- `pendingValue`: `ComboValue<T>[]`. Read-only. No attribute.
The values of the pending selection in the confirm mode of
`selectionCommit`, which Enter, the Apply button or `commitSelection()`
applies. Without a pending selection, the same as `value`.
- `locale`: `string`. Attribute: `locale`.
The locale of the component. Without it, the component takes its own
`lang`, else the locale of the nearest ancestor that has a `locale` (a
Expand Down Expand Up @@ -111,11 +138,23 @@ defineComponents(IgcComboComponent);
Removes focus from the component.
- `select(items?: Item<T> | Item<T>[]): void`
Selects options in the list by reference or by `valueKey` value. It does
not emit `igcChange`. Without an argument, it selects all items, or
clears the selection in single selection mode.
not emit `igcChange`. An object that `data` does not hold is selected as
it is. Without an argument, it selects all the items of `data`, or clears
the selection in single selection mode.
- `deselect(items?: Item<T> | Item<T>[]): void`
Deselects options in the list by reference or by `valueKey` value. It
does not emit `igcChange`. Without an argument, it deselects all items.
- `selectAllItems(ignoreFilter?: boolean = false): void`
Selects all the items that the list shows. It does not emit `igcChange`,
and does nothing in single selection mode.
- `deselectAllItems(ignoreFilter?: boolean = false): void`
Deselects all the items that the list shows. It does not emit `igcChange`.
- `commitSelection(): void`
Applies the pending selection of the confirm mode to `value`. It does not
emit `igcChange` or close the list.
- `cancelSelection(): void`
Puts `value` back as the pending selection of the confirm mode. It does
not close the list.
- `reportValidity(): boolean`
Checks validity. As for a native control, an invalid control emits
`invalid` and takes the focus. It shows its own validation messages, not
Expand All @@ -142,23 +181,30 @@ defineComponents(IgcComboComponent);
## Events

- `igcChange`
Emitted before the user changes the selection. Cancel the event to keep the selection.
Emitted before the user changes the selection, or applies the pending selection of the confirm mode (`type: 'commit'`). Cancel the event to keep the selection.
- `igcPendingChange`
Emitted in the confirm mode of `selectionCommit` before the user changes the pending selection. Cancel the event to keep the pending selection.
- `igcOpening`
Emitted before the user opens the list of options. Cancelable.
- `igcOpened`
Emitted after the list of options opens on a user action.
- `igcClosing`
Emitted before the user closes the list of options. Cancelable.
Emitted before the user closes the list of options. Cancelable. The `trigger` of the detail is the user action that closes the list.
- `igcClosed`
Emitted after the list of options closes on a user action.
Emitted after the list of options closes on a user action. The `trigger` of the detail is the user action that closes the list.
- `igcSearchInput`
Emitted when the user changes the text of the search input, or of the main input in single selection mode, and when a selection, a blur or the clear button clears the text. Also emitted with the same text when the case-sensitive icon changes the case of a search text.
- `igcDataRequest`
Emitted in remote filtering mode when the user scrolls near the end of the options, or to a placeholder of `totalItemCount`. Append the requested items to `data`. It is not emitted again until the length of `data`, the search text or its case changes, or the list opens again.

## Slots

- `prefix`: Renders content before the input of the combo.
- `suffix`: Renders content after the input of the combo.
- `header`: Renders a container before the list of options of the combo.
- `footer`: Renders a container after the list of options of the combo.
- `footer`: Renders a container after the list of options of the combo. In the confirm mode of `selectionCommit`, its default content is Cancel and Apply.
- `empty`: Renders content when the combo dropdown list has no items/data.
- `loading`: Renders content that replaces the default spinner while `loading` is set. It is in the input, so a click on it toggles the list, as on the toggle icon.
- `helper-text`: Renders content below the input of the combo.
- `toggle-icon`: Renders content that replaces the default toggle icon.
- `clear-icon`: Renders content that replaces the default clear icon.
Expand All @@ -184,17 +230,25 @@ defineComponents(IgcComboComponent);
- `list`: The list of options box of the combo.
- `item`: Each item in the list of options.
- `group-header`: Each group header in the list of options.
- `active`: Added to the item part when the item is active, and to the case-icon part while case-sensitive filtering is on.
- `selected`: Added to the item part when the item is selected.
- `active`: Added to the item part when the item is active, to the group-header part when the header is an active option of `groupSelection`, and to the case-icon part while case-sensitive filtering is on.
- `selected`: Added to the item part when the item is selected, and to the group-header part of `groupSelection` when all the shown items of the group are selected.
- `checkbox`: The checkbox of each item in the list.
- `checkbox-indicator`: The checkbox indicator of each item in the list.
- `checked`: Added to the checkbox and checkbox-indicator parts when the checkbox is checked.
- `indeterminate`: Added to the checkbox and checkbox-indicator parts of the select-all option, or of a group header of `groupSelection`, while only some of its shown items are selected.
- `select-all`: Added to the item part of the select-all option.
- `header`: The container holding the header content of the combo.
- `footer`: The container holding the footer content of the combo.
- `actions`: The container of the Cancel and Apply buttons of the confirm mode.
- `cancel-button`: The Cancel button of the confirm mode.
- `apply-button`: The Apply button of the confirm mode.
- `empty`: The container holding the empty content of the combo.
- `loading`: The indeterminate circular progress that replaces the toggle icon while `loading` is set. It has the color of the text.
- `placeholder`: Added to the item part of each item to load, which `totalItemCount` adds. Its skeleton has the color of the text.

## CSS custom properties

- `--ig-combo-item-indent`: The indent of the items under a group header option of `groupSelection`. Default is the indent of the tree: 12, 16 or 24 px by size, and 24 px in Indigo.
- `--ig-helper-min-lines`: The minimum number of lines below the control for the helper text and the validation messages: `1`, `2` or `3`. A message that shows then uses space that is already there, so the content below does not move. Set it on a container, such as a form, to apply it to all the controls in it. Default is `0`.

## CSS custom states
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"exports": {
".": "./src/index.js",
"./types": "./src/types.js",
"./extras": "./src/extras/index.js"
"./extras": "./src/extras/index.js",
"./extras/combo-data-source": "./src/extras/combo-data-source.js"
},
"imports": {
"#internals/*.js": "./src/internals/*.ts",
Expand Down
34 changes: 33 additions & 1 deletion public-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
"ColorFormat",
"ColorPickerMode",
"ColorPickerResourceStringsEN",
"ComboCloseTrigger",
"ComboFilteringMode",
"ComboGroupHeaderContext",
"ComboGroupHeaderTemplate",
"ComboItemTemplate",
"ComboResourceStringsEN",
"ComboSelectionCommit",
"ComboTemplateProps",
"ContentOrientation",
"CustomDateRange",
Expand Down Expand Up @@ -105,8 +108,10 @@
"IgcColorPickerComponent",
"IgcColorPickerComponentEventMap",
"IgcComboChangeEventArgs",
"IgcComboClosingEventArgs",
"IgcComboComponent",
"IgcComboComponentEventMap",
"IgcComboSearchInputEventArgs",
"IgcDatePickerComponent",
"IgcDatePickerComponentEventMap",
"IgcDateRangePickerComponent",
Expand Down Expand Up @@ -1217,9 +1222,11 @@
"display-key": "unknown",
"filtering-options": "FilteringOptions<T>",
"group-key": "Keys<T> | string | undefined",
"group-selection": "boolean",
"group-sorting": "\"asc\" | \"desc\" | \"none\" ('asc' | 'desc' | 'none')",
"invalid": "boolean",
"label": "string | undefined",
"loading": "boolean",
"locale": "string",
"name": "string",
"open": "boolean",
Expand All @@ -1228,7 +1235,10 @@
"placeholder-search": "string",
"required": "boolean",
"scroll-strategy": "PopoverScrollStrategy ('close' | 'hide' | 'scroll')",
"selection-commit": "ComboSelectionCommit ('confirm' | 'immediate')",
"show-select-all": "boolean",
"single-select": "boolean",
"total-item-count": "number | undefined",
"value": "ComboValue<T>[]",
"value-key": "Keys<T> | undefined"
},
Expand All @@ -1246,23 +1256,29 @@
"form": "readonly HTMLFormElement | null",
"groupHeaderTemplate": "ComboGroupHeaderTemplate<T>",
"groupKey": "Keys<T> | string | undefined",
"groupSelection": "boolean",
"groupSorting": "\"asc\" | \"desc\" | \"none\" ('asc' | 'desc' | 'none')",
"invalid": "boolean",
"itemTemplate": "ComboItemTemplate<T>",
"label": "string | undefined",
"loading": "boolean",
"locale": "string",
"name": "string",
"open": "boolean",
"outlined": "boolean",
"pendingValue": "readonly ComboValue<T>[]",
"placeholder": "string | undefined",
"placeholderSearch": "string",
"required": "boolean",
"resourceStrings": "Required<IComboResourceStrings>",
"scrollStrategy": "PopoverScrollStrategy ('close' | 'hide' | 'scroll')",
"selection": "readonly T[]",
"selectionCommit": "ComboSelectionCommit ('confirm' | 'immediate')",
"showSelectAll": "boolean",
"singleSelect": "boolean",
"static formAssociated": "readonly boolean",
"static tagName": "readonly string",
"totalItemCount": "number | undefined",
"validationMessage": "readonly string",
"validity": "readonly ValidityState",
"value": "ComboValue<T>[]",
Expand All @@ -1271,12 +1287,16 @@
},
"methods": {
"blur": "() => void",
"cancelSelection": "() => void",
"checkValidity": "() => boolean",
"commitSelection": "() => void",
"deselect": "(items?: Item<T> | Item<T>[]) => void",
"deselectAllItems": "(ignoreFilter?: boolean) => void",
"focus": "(options?: FocusOptions) => void",
"hide": "() => Promise<boolean>",
"reportValidity": "() => boolean",
"select": "(items?: Item<T> | Item<T>[]) => void",
"selectAllItems": "(ignoreFilter?: boolean) => void",
"setCustomValidity": "(message: string) => void",
"show": "() => Promise<boolean>",
"static register": "() => void",
Expand All @@ -1286,8 +1306,11 @@
"igcChange": "unknown",
"igcClosed": "unknown",
"igcClosing": "unknown",
"igcDataRequest": "unknown",
"igcOpened": "unknown",
"igcOpening": "unknown"
"igcOpening": "unknown",
"igcPendingChange": "unknown",
"igcSearchInput": "unknown"
},
"slots": [
"clear-icon",
Expand All @@ -1297,13 +1320,17 @@
"header",
"helper-text",
"invalid",
"loading",
"prefix",
"suffix",
"toggle-icon",
"value-missing"
],
"cssParts": [
"actions",
"active",
"apply-button",
"cancel-button",
"case-icon",
"checkbox",
"checkbox-indicator",
Expand All @@ -1316,19 +1343,24 @@
"group-header",
"header",
"helper-text",
"indeterminate",
"input",
"item",
"label",
"list",
"list-wrapper",
"loading",
"native-input",
"placeholder",
"prefix",
"search-input",
"select-all",
"selected",
"suffix",
"toggle-icon"
],
"cssProperties": [
"--ig-combo-item-indent",
"--ig-helper-min-lines"
]
},
Expand Down
4 changes: 4 additions & 0 deletions scripts/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
"./extras": {
"types": "./extras/index.d.ts",
"default": "./extras/index.js"
},
"./extras/combo-data-source": {
"types": "./extras/combo-data-source.d.ts",
"default": "./extras/combo-data-source.js"
}
},
"imports": {
Expand Down
2 changes: 1 addition & 1 deletion src/components/chip/themes/shared/chip.common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ $theme: $material;
}

::slotted(igc-circular-progress) {
--diameter: #{sizable(rem(14px), rem(18px), rem(24px))};
--ig-circular-bar-diameter: #{sizable(rem(14px), rem(18px), rem(24px))};
}
}

Expand Down
Loading
Loading