From ac3432b0ec04f5cc1a2ac40e9dc7931d0dcf8f57 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 4 Nov 2026 13:24:10 +0200 Subject: [PATCH 1/5] feat(combo): update combo overview samples --- live-editing/configs/ComboConfigGenerator.ts | 70 +++++++++++++++++- .../combo-disabled.component.html | 24 +++++++ .../combo-disabled.component.scss | 35 +++++++++ .../combo-disabled.component.ts | 37 ++++++++++ .../combo-dropdown-size.component.html | 20 ++++++ .../combo-dropdown-size.component.scss | 48 +++++++++++++ .../combo-dropdown-size.component.ts | 53 ++++++++++++++ .../combo-overview.component.html | 14 ++++ .../combo-overview.component.scss | 15 ++++ .../combo-overview.component.ts | 47 ++++++++++++ .../combo-search-input.component.html | 16 +++++ .../combo-search-input.component.scss | 71 +++++++++++++++++++ .../combo-search-input.component.ts | 40 +++++++++++ .../combo-size/combo-size.component.html | 22 ++++++ .../combo-size/combo-size.component.scss | 44 ++++++++++++ .../combo/combo-size/combo-size.component.ts | 62 ++++++++++++++++ .../combo-states/combo-states.component.html | 19 +++++ .../combo-states/combo-states.component.scss | 69 ++++++++++++++++++ .../combo-states/combo-states.component.ts | 60 ++++++++++++++++ .../combo-styling.component.html | 21 +++--- .../combo-styling.component.scss | 58 ++++++++++----- .../combo-styling/combo-styling.component.ts | 56 +++++++++------ src/app/lists/combo/combo-styling/layout.scss | 3 - .../combo-tailwind-styling.component.html | 21 +++--- .../combo-tailwind-styling.component.scss | 25 ++++++- .../combo-tailwind-styling.component.ts | 54 ++++++++------ .../combo-type/combo-type.component.html | 21 ++++++ .../combo-type/combo-type.component.scss | 34 +++++++++ .../combo/combo-type/combo-type.component.ts | 51 +++++++++++++ .../combo-validation.component.html | 24 +++++++ .../combo-validation.component.scss | 56 +++++++++++++++ .../combo-validation.component.ts | 70 ++++++++++++++++++ src/app/lists/lists-routes-data.ts | 8 +++ src/app/lists/lists.routes.ts | 48 +++++++++++++ 34 files changed, 1226 insertions(+), 90 deletions(-) create mode 100644 src/app/lists/combo/combo-disabled/combo-disabled.component.html create mode 100644 src/app/lists/combo/combo-disabled/combo-disabled.component.scss create mode 100644 src/app/lists/combo/combo-disabled/combo-disabled.component.ts create mode 100644 src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html create mode 100644 src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss create mode 100644 src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts create mode 100644 src/app/lists/combo/combo-overview/combo-overview.component.html create mode 100644 src/app/lists/combo/combo-overview/combo-overview.component.scss create mode 100644 src/app/lists/combo/combo-overview/combo-overview.component.ts create mode 100644 src/app/lists/combo/combo-search-input/combo-search-input.component.html create mode 100644 src/app/lists/combo/combo-search-input/combo-search-input.component.scss create mode 100644 src/app/lists/combo/combo-search-input/combo-search-input.component.ts create mode 100644 src/app/lists/combo/combo-size/combo-size.component.html create mode 100644 src/app/lists/combo/combo-size/combo-size.component.scss create mode 100644 src/app/lists/combo/combo-size/combo-size.component.ts create mode 100644 src/app/lists/combo/combo-states/combo-states.component.html create mode 100644 src/app/lists/combo/combo-states/combo-states.component.scss create mode 100644 src/app/lists/combo/combo-states/combo-states.component.ts delete mode 100644 src/app/lists/combo/combo-styling/layout.scss create mode 100644 src/app/lists/combo/combo-type/combo-type.component.html create mode 100644 src/app/lists/combo/combo-type/combo-type.component.scss create mode 100644 src/app/lists/combo/combo-type/combo-type.component.ts create mode 100644 src/app/lists/combo/combo-validation/combo-validation.component.html create mode 100644 src/app/lists/combo/combo-validation/combo-validation.component.scss create mode 100644 src/app/lists/combo/combo-validation/combo-validation.component.ts diff --git a/live-editing/configs/ComboConfigGenerator.ts b/live-editing/configs/ComboConfigGenerator.ts index 74e14111ee..a45aa41405 100644 --- a/live-editing/configs/ComboConfigGenerator.ts +++ b/live-editing/configs/ComboConfigGenerator.ts @@ -27,10 +27,76 @@ export class ComboConfigGenerator implements IConfigGenerator { shortenComponentPathBy: '/lists/combo/' })); + // combo overview configs.push(new Config({ - additionalFiles: ['/src/app/data/heroData.ts', '/src/app/lists/combo/combo-styling/layout.scss'], appConfig: BaseAppConfig, - component: 'ComboStylingComponent' + component: 'ComboOverviewComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo type + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboTypeComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo disabled + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboDisabledComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo size + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboSizeComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo states + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboStatesComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo validation + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboValidationComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo dropdown size + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboDropdownSizeComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo search input + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboSearchInputComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo styling + configs.push(new Config({ + appConfig: BaseAppConfig, + component: 'ComboStylingComponent', + shortenComponentPathBy: '/lists/combo/' + })); + + // combo tailwind styling + configs.push(new Config({ + additionalDependencies: ['tailwindcss', '@tailwindcss/postcss'], + additionalFiles: ['.postcssrc.json'], + appConfig: BaseAppConfig, + component: 'ComboTailwindStylingComponent', + shortenComponentPathBy: '/lists/combo/' })); configs.push(new Config({ diff --git a/src/app/lists/combo/combo-disabled/combo-disabled.component.html b/src/app/lists/combo/combo-disabled/combo-disabled.component.html new file mode 100644 index 0000000000..a37714a5ae --- /dev/null +++ b/src/app/lists/combo/combo-disabled/combo-disabled.component.html @@ -0,0 +1,24 @@ +
+ + Enabled + Disabled + @for (row of rows; track $index) { + @let groupStart = $index === 2; + {{ row.label }} + @for (disabled of [false, true]; track disabled) { +
+ + +
+ } + } +
diff --git a/src/app/lists/combo/combo-disabled/combo-disabled.component.scss b/src/app/lists/combo/combo-disabled/combo-disabled.component.scss new file mode 100644 index 0000000000..267bee027b --- /dev/null +++ b/src/app/lists/combo/combo-disabled/combo-disabled.component.scss @@ -0,0 +1,35 @@ +:host { + /* styles.scss asks the page for the large size; the combos keep their own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.states { + display: grid; + grid-template-columns: max-content repeat(2, minmax(0, 17.4375rem)); + width: 100%; + justify-content: center; + align-items: center; + column-gap: 1.75rem; + row-gap: 1.5rem; +} + +.group-start { + margin-top: 1.5rem; +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} + +.state-column { + justify-self: center; +} diff --git a/src/app/lists/combo/combo-disabled/combo-disabled.component.ts b/src/app/lists/combo/combo-disabled/combo-disabled.component.ts new file mode 100644 index 0000000000..4a127857bb --- /dev/null +++ b/src/app/lists/combo/combo-disabled/combo-disabled.component.ts @@ -0,0 +1,37 @@ +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IgxInputGroupType } from 'igniteui-angular/input-group'; + +interface Country { + id: string; + name: string; + region: string; +} + +interface DisabledRow { + label: string; + type: IgxInputGroupType; + value: string[]; +} + +@Component({ + selector: 'app-combo-disabled', + styleUrls: ['./combo-disabled.component.scss'], + templateUrl: './combo-disabled.component.html', + imports: [IgxComboComponent, FormsModule] +}) +export class ComboDisabledComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; + + public rows: DisabledRow[] = [ + { label: 'Idle', type: 'border', value: [] }, + { label: 'Filled', type: 'border', value: ['BY', 'BE'] }, + { label: 'Idle', type: 'box', value: [] }, + { label: 'Filled', type: 'box', value: ['BY', 'BE'] } + ]; +} diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html new file mode 100644 index 0000000000..49f28cd3d1 --- /dev/null +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html @@ -0,0 +1,20 @@ +
+ @for (size of sizes; track size.label) { +
+ {{ size.label }} + + +
+ } +
diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss new file mode 100644 index 0000000000..4a423025d5 --- /dev/null +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss @@ -0,0 +1,48 @@ +:host { + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.sizes { + display: grid; + grid-template-columns: repeat(3, 11.25rem); + column-gap: 1rem; +} + +.size { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +.dropdown { + width: 100%; +} + +/* Only the dropdown of the combo is shown, so the input field is hidden. */ +.dropdown ::ng-deep igx-combo > igx-input-group { + display: none; +} + + +.small { + --ig-size: var(--ig-size-small); +} + +.medium { + --ig-size: var(--ig-size-medium); +} + +.large { + --ig-size: var(--ig-size-large); +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts new file mode 100644 index 0000000000..9dc4370bc7 --- /dev/null +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts @@ -0,0 +1,53 @@ +import { Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IBaseCancelableBrowserEventArgs } from 'igniteui-angular/core'; +import { forkJoin, take } from 'rxjs'; + +interface Option { + id: number; + name: string; + group: string; +} + +interface DropdownSize { + label: string; + className: string; +} + +@Component({ + selector: 'app-combo-dropdown-size', + styleUrls: ['./combo-dropdown-size.component.scss'], + templateUrl: './combo-dropdown-size.component.html', + imports: [IgxComboComponent] +}) +export class ComboDropdownSizeComponent { + public options: Option[] = [1, 2, 3].map((id) => ({ id, name: 'Item', group: 'Header' })); + + public sizes: DropdownSize[] = [ + { label: 'Small', className: 'small' }, + { label: 'Medium', className: 'medium' }, + { label: 'Large', className: 'large' } + ]; + + private combos = viewChildren(IgxComboComponent); + + constructor() { + const element = inject>(ElementRef).nativeElement; + + // The combos are shown open. Opening a combo moves the focus to its search input, so + // the sample is inert until the combos open and the page keeps its focus. + afterNextRender(() => { + const combos = this.combos(); + element.inert = true; + forkJoin(combos.map((combo) => combo.opened.pipe(take(1)))).subscribe(() => { + element.inert = false; + }); + combos.forEach((combo) => combo.open()); + }); + } + + // The input fields are hidden, so the dropdowns stay open and each one works on its own. + public keepOpen(event: IBaseCancelableBrowserEventArgs): void { + event.cancel = true; + } +} diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.html b/src/app/lists/combo/combo-overview/combo-overview.component.html new file mode 100644 index 0000000000..075b1e708d --- /dev/null +++ b/src/app/lists/combo/combo-overview/combo-overview.component.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.scss b/src/app/lists/combo/combo-overview/combo-overview.component.scss new file mode 100644 index 0000000000..d38c5d64f5 --- /dev/null +++ b/src/app/lists/combo/combo-overview/combo-overview.component.scss @@ -0,0 +1,15 @@ +:host { + /* styles.scss asks the page for the large size; the combo keeps its own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.locations { + width: 22.5rem; +} diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.ts b/src/app/lists/combo/combo-overview/combo-overview.component.ts new file mode 100644 index 0000000000..de9f27f49d --- /dev/null +++ b/src/app/lists/combo/combo-overview/combo-overview.component.ts @@ -0,0 +1,47 @@ +import { Component, ElementRef, afterNextRender, inject, viewChild } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IgxIconComponent, IgxIconService } from 'igniteui-angular/icon'; +import { IgxLabelDirective, IgxPrefixDirective } from 'igniteui-angular/input-group'; +import { take } from 'rxjs'; + +const placeIcon = ''; + +interface City { + id: string; + name: string; + country: string; +} + +@Component({ + selector: 'app-combo-overview', + styleUrls: ['./combo-overview.component.scss'], + templateUrl: './combo-overview.component.html', + imports: [IgxComboComponent, IgxLabelDirective, IgxPrefixDirective, IgxIconComponent] +}) +export class ComboOverviewComponent { + public cities: City[] = [ + { id: 'BG01', name: 'Sofia', country: 'Country of Bulgaria' }, + { id: 'BG02', name: 'Plovdiv', country: 'Country of Bulgaria' }, + { id: 'BG03', name: 'Varna', country: 'Country of Bulgaria' }, + { id: 'BG04', name: 'Burgas', country: 'Country of Bulgaria' }, + { id: 'BG05', name: 'Pleven', country: 'Country of Bulgaria' } + ]; + + private combo = viewChild.required(IgxComboComponent); + + constructor() { + const element = inject>(ElementRef).nativeElement; + inject(IgxIconService).addSvgIconFromText('place', placeIcon, 'material'); + + // The combo is shown open. Opening it moves the focus to its search input, so the + // sample is inert until the combo opens and the page keeps its focus. + afterNextRender(() => { + const combo = this.combo(); + element.inert = true; + combo.opened.pipe(take(1)).subscribe(() => { + element.inert = false; + }); + combo.open(); + }); + } +} diff --git a/src/app/lists/combo/combo-search-input/combo-search-input.component.html b/src/app/lists/combo/combo-search-input/combo-search-input.component.html new file mode 100644 index 0000000000..6d1a9d62cc --- /dev/null +++ b/src/app/lists/combo/combo-search-input/combo-search-input.component.html @@ -0,0 +1,16 @@ +
+ @for (state of states; track state.label) { +
+ {{ state.label }} + + +
+ } +
diff --git a/src/app/lists/combo/combo-search-input/combo-search-input.component.scss b/src/app/lists/combo/combo-search-input/combo-search-input.component.scss new file mode 100644 index 0000000000..120955598e --- /dev/null +++ b/src/app/lists/combo/combo-search-input/combo-search-input.component.scss @@ -0,0 +1,71 @@ +:host { + /* styles.scss asks the page for the large size; the combos keep their own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.states { + display: grid; + grid-template-columns: repeat(3, 11.25rem); + grid-template-rows: repeat(2, 5.5rem); + column-gap: 1rem; + row-gap: 1rem; +} + +.state { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +.search { + width: 100%; + pointer-events: none; +} + +/* Only the search input of the combo dropdown is shown. */ +.search ::ng-deep igx-combo > igx-input-group, +.search ::ng-deep .igx-combo__add { + display: none; +} + +/* The open dropdown takes no pointer input either. */ +.search ::ng-deep .igx-overlay__content { + pointer-events: none; +} + +.search.hover ::ng-deep .igx-combo__search igx-input-group { + --idle-bottom-line-color: var(--hover-bottom-line-color); +} + +.search.disabled ::ng-deep .igx-combo__search igx-input-group { + --idle-bottom-line-color: var(--disabled-bottom-line-color); + --placeholder-color: var(--disabled-placeholder-color); +} + +.search.filled ::ng-deep .igx-combo__search igx-input-group { + --placeholder-color: var(--filled-text-color); +} + +.search.focused ::ng-deep .igx-combo__search igx-input-group { + --idle-bottom-line-color: var(--focused-bottom-line-color); + --hover-bottom-line-color: var(--focused-bottom-line-color); +} + +/* the input group shows its two pixels thick focused line */ +.search.focused ::ng-deep .igx-combo__search .igx-input-group__bundle::after { + scale: 1; +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} diff --git a/src/app/lists/combo/combo-search-input/combo-search-input.component.ts b/src/app/lists/combo/combo-search-input/combo-search-input.component.ts new file mode 100644 index 0000000000..56a2806670 --- /dev/null +++ b/src/app/lists/combo/combo-search-input/combo-search-input.component.ts @@ -0,0 +1,40 @@ +import { Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; + +interface SearchState { + label: string; + className?: string; + text?: string; +} + +@Component({ + selector: 'app-combo-search-input', + styleUrls: ['./combo-search-input.component.scss'], + templateUrl: './combo-search-input.component.html', + imports: [IgxComboComponent] +}) +export class ComboSearchInputComponent { + // The search input states come from the pointer and the keyboard, so the `hover`, + // `disabled`, `filled` and `focused` classes show them on the display-only combos. + public states: SearchState[] = [ + { label: 'Idle' }, + { label: 'Idle & Hover', className: 'hover' }, + { label: 'Disabled', className: 'disabled' }, + { label: 'Filled', className: 'filled', text: 'Input text' }, + { label: 'Filled & Hover', className: 'filled hover', text: 'Input text' }, + { label: 'Focused', className: 'filled focused', text: 'Input text' } + ]; + + private combos = viewChildren(IgxComboComponent); + + constructor() { + // The search inputs are display-only, so the sample is inert. Opening a combo moves the + // focus to its search input, and the inert sample also keeps the focus on the page. + inject>(ElementRef).nativeElement.inert = true; + + // The combos are shown open. + afterNextRender(() => { + this.combos().forEach((combo) => combo.open()); + }); + } +} diff --git a/src/app/lists/combo/combo-size/combo-size.component.html b/src/app/lists/combo/combo-size/combo-size.component.html new file mode 100644 index 0000000000..7677e706e0 --- /dev/null +++ b/src/app/lists/combo/combo-size/combo-size.component.html @@ -0,0 +1,22 @@ +
+ + @for (size of sizes; track size.label) { + {{ size.label }} + } + @for (type of types; track type.label) { + {{ type.label }} + @for (size of sizes; track size.label) { + + + } + } +
diff --git a/src/app/lists/combo/combo-size/combo-size.component.scss b/src/app/lists/combo/combo-size/combo-size.component.scss new file mode 100644 index 0000000000..a89cfd43a3 --- /dev/null +++ b/src/app/lists/combo/combo-size/combo-size.component.scss @@ -0,0 +1,44 @@ +:host { + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.sizes { + display: grid; + grid-template-columns: max-content repeat(3, minmax(0, 17.4375rem)); + width: 100%; + justify-content: center; + grid-template-rows: auto repeat(2, 17rem); + align-items: start; + column-gap: 1.75rem; + row-gap: 1rem; +} + +.type-label { + padding-top: 0.75rem; +} + +.small { + --ig-size: var(--ig-size-small); +} + +.medium { + --ig-size: var(--ig-size-medium); +} + +.large { + --ig-size: var(--ig-size-large); +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} + +.state-column { + justify-self: center; +} diff --git a/src/app/lists/combo/combo-size/combo-size.component.ts b/src/app/lists/combo/combo-size/combo-size.component.ts new file mode 100644 index 0000000000..0a0c4af1fa --- /dev/null +++ b/src/app/lists/combo/combo-size/combo-size.component.ts @@ -0,0 +1,62 @@ +import { Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IgxInputGroupType } from 'igniteui-angular/input-group'; +import { forkJoin, take } from 'rxjs'; + +interface Country { + id: string; + name: string; + region: string; +} + +interface ComboSize { + label: string; + className: string; +} + +interface ComboType { + label: string; + type: IgxInputGroupType; +} + +@Component({ + selector: 'app-combo-size', + styleUrls: ['./combo-size.component.scss'], + templateUrl: './combo-size.component.html', + imports: [IgxComboComponent] +}) +export class ComboSizeComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; + + public sizes: ComboSize[] = [ + { label: 'Small', className: 'small' }, + { label: 'Medium', className: 'medium' }, + { label: 'Large', className: 'large' } + ]; + + public types: ComboType[] = [ + { label: 'Border Type', type: 'border' }, + { label: 'Box Type', type: 'box' } + ]; + + private combos = viewChildren(IgxComboComponent); + + constructor() { + const element = inject>(ElementRef).nativeElement; + + // The combos are shown open. Opening a combo moves the focus to its search input, so + // the sample is inert until the combos open and the page keeps its focus. + afterNextRender(() => { + const combos = this.combos(); + element.inert = true; + forkJoin(combos.map((combo) => combo.opened.pipe(take(1)))).subscribe(() => { + element.inert = false; + }); + combos.forEach((combo) => combo.open()); + }); + } +} diff --git a/src/app/lists/combo/combo-states/combo-states.component.html b/src/app/lists/combo/combo-states/combo-states.component.html new file mode 100644 index 0000000000..e67c8074b9 --- /dev/null +++ b/src/app/lists/combo/combo-states/combo-states.component.html @@ -0,0 +1,19 @@ +
+ @for (state of states; track state.label) { +
+ {{ state.label }} + + +
+ } +
diff --git a/src/app/lists/combo/combo-states/combo-states.component.scss b/src/app/lists/combo/combo-states/combo-states.component.scss new file mode 100644 index 0000000000..1e7cbd02a2 --- /dev/null +++ b/src/app/lists/combo/combo-states/combo-states.component.scss @@ -0,0 +1,69 @@ +:host { + /* styles.scss asks the page for the large size; the combos keep their own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.states { + display: grid; + grid-template-columns: repeat(3, minmax(0, 17.4375rem)); + width: 100%; + justify-content: center; + column-gap: 1.75rem; + row-gap: 1.25rem; +} + +.state { + display: flex; + flex-direction: column; + min-width: 0; + align-items: center; + gap: 0.5rem; +} + +.state-combo { + width: 100%; + pointer-events: none; +} + +/* The open dropdown takes no pointer input either. */ +.state-combo ::ng-deep .igx-overlay__content { + pointer-events: none; +} + +/* The states belong to the combo's own input group, not to the search input in its dropdown. */ +.state-combo.hover > ::ng-deep igx-input-group { + --border-color: var(--hover-border-color); + --idle-bottom-line-color: var(--hover-bottom-line-color); +} + +.state-combo.focused > ::ng-deep igx-input-group { + --border-color: var(--focused-border-color); + --idle-bottom-line-color: var(--focused-bottom-line-color); +} + +.state-combo.focused > ::ng-deep igx-input-group .igx-input-group__bundle { + box-shadow: inset 0 0 0 0.125rem var(--focused-border-color); +} + +.state-combo.focused > ::ng-deep igx-input-group .igx-input-group__toggle-button { + color: var(--toggle-button-foreground-focus); + background: var(--toggle-button-background-focus--border); +} + +.state-combo.focused > ::ng-deep igx-input-group .igx-input-group__clear-button { + color: var(--clear-button-foreground-focus); + background: var(--clear-button-background-focus); +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} diff --git a/src/app/lists/combo/combo-states/combo-states.component.ts b/src/app/lists/combo/combo-states/combo-states.component.ts new file mode 100644 index 0000000000..6c2e8dc297 --- /dev/null +++ b/src/app/lists/combo/combo-states/combo-states.component.ts @@ -0,0 +1,60 @@ +import { Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { OverlaySettings } from 'igniteui-angular/core'; + +interface Country { + id: string; + name: string; + region: string; +} + +interface ComboState { + label: string; + className?: string; + value: string[]; + open?: boolean; +} + +@Component({ + selector: 'app-combo-states', + styleUrls: ['./combo-states.component.scss'], + templateUrl: './combo-states.component.html', + imports: [IgxComboComponent, FormsModule] +}) +export class ComboStatesComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; + + // Hover and focus come from the pointer and the keyboard, so the `hover` and `focused` + // classes show them on the display-only combos. + public states: ComboState[] = [ + { label: 'Idle', value: [] }, + { label: 'Idle & Hover', className: 'hover', value: [] }, + { label: 'Filled', value: ['BY', 'BE'] }, + { label: 'Filled & Hover', className: 'hover', value: ['BY', 'BE'] }, + { label: 'Focused', className: 'focused', value: ['BY', 'BE'] }, + { label: 'Focused (Dropdown On)', className: 'focused', value: ['BY', 'BE'], open: true } + ]; + + // The open dropdown is display-only, so a click elsewhere does not close it. + public overlaySettings: OverlaySettings = { closeOnOutsideClick: false }; + + private combos = viewChildren(IgxComboComponent); + + constructor() { + // The combos are display-only, so the sample is inert. Opening a combo moves the focus + // to its search input, and the inert sample also keeps the focus on the page. + inject>(ElementRef).nativeElement.inert = true; + + // The last combo is shown with its dropdown open. + afterNextRender(() => { + this.combos() + .filter((_, index) => this.states[index].open) + .forEach((combo) => combo.open()); + }); + } +} diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.html b/src/app/lists/combo/combo-styling/combo-styling.component.html index 36303918d3..0b437c6d1e 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.html +++ b/src/app/lists/combo/combo-styling/combo-styling.component.html @@ -1,10 +1,11 @@ -
- - - - -
- - + + diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.scss b/src/app/lists/combo/combo-styling/combo-styling.component.scss index 2348955c2f..6feace04af 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.scss +++ b/src/app/lists/combo/combo-styling/combo-styling.component.scss @@ -1,23 +1,45 @@ -@use "layout.scss"; -@use "igniteui-angular/theming" as *; +@use "sass:meta"; +@include meta.load-css("igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"); -$custom-drop-down-theme: drop-down-theme( - $background-color: #57a5cd, -); +app-combo-styling { + /* styles.scss asks the page for the large size; the combo keeps its own + default medium size here. */ + --ig-size: var(--ig-size-medium); -$custom-combo-theme: combo-theme( - $search-separator-border-color: #1d3743, - $toggle-button-background: #57a5cd, -); + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} -$custom-checkbox-theme: checkbox-theme( - $border-radius: 10px, - $fill-color: #1d3743, - $empty-color: #1d3743, -); +.styled-combo { + --ig-font-family: "Titillium Web", sans-serif; + --ig-input-group-border-color: #1377d5; + --ig-input-group-hover-border-color: #1377d5; + --ig-input-group-focused-border-color: #1377d5; + --ig-input-group-filled-text-color: #212121; + --ig-input-group-focused-bottom-line-color: #007ccf; + --ig-combo-toggle-button-background: #e0e0e0; + --ig-combo-toggle-button-background-focus: #e0e0e0; + --ig-combo-toggle-button-background-focus--border: #e0e0e0; + --ig-combo-toggle-button-foreground: #212121; + --ig-combo-toggle-button-foreground-focus: #212121; + --ig-combo-toggle-button-foreground-filled: #212121; + --ig-drop-down-background-color: #e6f2ff; + --ig-drop-down-header-text-color: #005dcc; + --ig-drop-down-item-text-color: #212121; + --ig-drop-down-hover-item-background: #cce4ff; + --ig-drop-down-focused-item-background: #cce4ff; + --ig-drop-down-selected-item-background: #4ca7e3; + --ig-drop-down-selected-item-text-color: #000; + --ig-drop-down-selected-hover-item-background: #4ca7e3; + --ig-drop-down-selected-hover-item-text-color: #000; + --ig-drop-down-selected-focus-item-background: #4ca7e3; + --ig-drop-down-selected-focus-item-text-color: #000; + --ig-checkbox-empty-color: #005dcc; + --ig-checkbox-fill-color: #005dcc; + --ig-checkbox-tick-color: #fff; -:host { - @include tokens($custom-drop-down-theme); - @include tokens($custom-combo-theme); - @include tokens($custom-checkbox-theme); + width: 17.4375rem; } diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.ts b/src/app/lists/combo/combo-styling/combo-styling.component.ts index 63ebea26f0..ee30b02a4e 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.ts +++ b/src/app/lists/combo/combo-styling/combo-styling.component.ts @@ -1,34 +1,44 @@ -import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { IComboSelectionChangingEventArgs, IgxComboComponent } from 'igniteui-angular/combo'; -import { IgxToastComponent } from 'igniteui-angular/toast'; -import { VerticalAlignment } from 'igniteui-angular/core'; -import { getHeroWeaponsData, IHeroWeapon } from '../../../data/heroData'; +import { Component, ElementRef, ViewEncapsulation, afterNextRender, inject, viewChild } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { take } from 'rxjs'; + +interface Country { + id: string; + name: string; + region: string; +} @Component({ - selector: 'app-combo', + selector: 'app-combo-styling', + encapsulation: ViewEncapsulation.None, styleUrls: ['./combo-styling.component.scss'], templateUrl: './combo-styling.component.html', - imports: [IgxComboComponent, IgxToastComponent] + imports: [IgxComboComponent, FormsModule] }) -export class ComboStylingComponent implements OnInit { - elem = inject(ElementRef); +export class ComboStylingComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; - @ViewChild('loadToast', { read: IgxToastComponent, static: true }) - public loadToast: IgxToastComponent; + public selection = ['BY']; - public weaponsData: IHeroWeapon[] = []; - - public ngOnInit() { - this.weaponsData = getHeroWeaponsData(); - } + private combo = viewChild.required(IgxComboComponent); - public setWeaponsLimit(event: IComboSelectionChangingEventArgs) { - this.loadToast.positionSettings.verticalDirection = VerticalAlignment.Middle; - // this.loadToast.autoHide = true; + constructor() { + const element = inject>(ElementRef).nativeElement; - if (event.newValue.length > 2) { - event.cancel = true; - this.loadToast.open('Choose only two items'); - } + // The combo is shown open. Opening it moves the focus to its search input, so the + // sample is inert until the combo opens and the page keeps its focus. + afterNextRender(() => { + const combo = this.combo(); + element.inert = true; + combo.opened.pipe(take(1)).subscribe(() => { + element.inert = false; + }); + combo.open(); + }); } } diff --git a/src/app/lists/combo/combo-styling/layout.scss b/src/app/lists/combo/combo-styling/layout.scss deleted file mode 100644 index 82f1579d5d..0000000000 --- a/src/app/lists/combo/combo-styling/layout.scss +++ /dev/null @@ -1,3 +0,0 @@ -.control-wrapper { - padding: 8px; -} \ No newline at end of file diff --git a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html index 184c269959..259e0133ff 100644 --- a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html +++ b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html @@ -1,10 +1,11 @@ -
- - - - -
- - + + diff --git a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.scss b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.scss index 99f78fbca7..69822a7ff4 100644 --- a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.scss +++ b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.scss @@ -1,3 +1,24 @@ -.control-wrapper { - padding: 8px; +@use "sass:meta"; +@import url("https://use.typekit.net/bng2zgw.css"); +@include meta.load-css("igniteui-angular/lib/core/styles/themes/presets/igniteui-bootstrap-light"); + +app-combo-tailwind-styling { + /* The combo palette that the utilities in the template read. */ + --color-combo-border: #a9b8cc; + --color-combo-toggle: #e5ebf3; + --color-combo-surface: #f3f6fa; + --color-combo-selected: #d2dbe8; + --color-combo-accent: #7d91ab; + --color-combo-header: #005dcc; + --color-combo-ink: #212121; + + /* styles.scss asks the page for the large size; the combo keeps its own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; } diff --git a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.ts b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.ts index 0bb9922864..35fc05d1f4 100644 --- a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.ts +++ b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.ts @@ -1,34 +1,44 @@ -import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { IComboSelectionChangingEventArgs, IgxComboComponent } from 'igniteui-angular/combo'; -import { IgxToastComponent } from 'igniteui-angular/toast'; -import { VerticalAlignment } from 'igniteui-angular/core'; -import { getHeroWeaponsData, IHeroWeapon } from '../../../data/heroData'; +import { Component, ElementRef, ViewEncapsulation, afterNextRender, inject, viewChild } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { take } from 'rxjs'; + +interface Country { + id: string; + name: string; + region: string; +} @Component({ selector: 'app-combo-tailwind-styling', + encapsulation: ViewEncapsulation.None, styleUrls: ['./combo-tailwind-styling.component.scss'], templateUrl: './combo-tailwind-styling.component.html', - imports: [IgxComboComponent, IgxToastComponent] + imports: [IgxComboComponent, FormsModule] }) -export class ComboTailwindStylingComponent implements OnInit { - elem = inject(ElementRef); +export class ComboTailwindStylingComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; - @ViewChild('loadToast', { read: IgxToastComponent, static: true }) - public loadToast: IgxToastComponent; + public selection = ['BY']; - public weaponsData: IHeroWeapon[] = []; - - public ngOnInit() { - this.weaponsData = getHeroWeaponsData(); - } + private combo = viewChild.required(IgxComboComponent); - public setWeaponsLimit(event: IComboSelectionChangingEventArgs) { - this.loadToast.positionSettings.verticalDirection = VerticalAlignment.Middle; - // this.loadToast.autoHide = true; + constructor() { + const element = inject>(ElementRef).nativeElement; - if (event.newValue.length > 2) { - event.cancel = true; - this.loadToast.open('Choose only two items'); - } + // The combo is shown open. Opening it moves the focus to its search input, so the + // sample is inert until the combo opens and the page keeps its focus. + afterNextRender(() => { + const combo = this.combo(); + element.inert = true; + combo.opened.pipe(take(1)).subscribe(() => { + element.inert = false; + }); + combo.open(); + }); } } diff --git a/src/app/lists/combo/combo-type/combo-type.component.html b/src/app/lists/combo/combo-type/combo-type.component.html new file mode 100644 index 0000000000..5242e11b6c --- /dev/null +++ b/src/app/lists/combo/combo-type/combo-type.component.html @@ -0,0 +1,21 @@ +
+ @for (type of types; track type.label) { +
+ {{ type.label }} + + + + + + +
+ } +
diff --git a/src/app/lists/combo/combo-type/combo-type.component.scss b/src/app/lists/combo/combo-type/combo-type.component.scss new file mode 100644 index 0000000000..f45cb9a3d9 --- /dev/null +++ b/src/app/lists/combo/combo-type/combo-type.component.scss @@ -0,0 +1,34 @@ +:host { + /* styles.scss asks the page for the large size; the combos keep their own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: flex-start; + justify-content: center; + height: 100%; + padding: 2rem 1rem; +} + +.types { + display: grid; + grid-template-columns: repeat(2, minmax(0, 22.5rem)); + width: 100%; + justify-content: center; + column-gap: 3.75rem; +} + +.type { + display: flex; + flex-direction: column; + min-width: 0; + gap: 0.75rem; +} + +.type-label { + justify-self: center; + text-align: center; + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} diff --git a/src/app/lists/combo/combo-type/combo-type.component.ts b/src/app/lists/combo/combo-type/combo-type.component.ts new file mode 100644 index 0000000000..dbe0a06be9 --- /dev/null +++ b/src/app/lists/combo/combo-type/combo-type.component.ts @@ -0,0 +1,51 @@ +import { Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IgxIconComponent, IgxIconService } from 'igniteui-angular/icon'; +import { IgxInputGroupType, IgxLabelDirective, IgxPrefixDirective } from 'igniteui-angular/input-group'; +import { forkJoin, take } from 'rxjs'; + +const languageIcon = ''; + +interface Option { + id: number; + name: string; + group: string; +} + +interface ComboType { + label: string; + type: IgxInputGroupType; +} + +@Component({ + selector: 'app-combo-type', + styleUrls: ['./combo-type.component.scss'], + templateUrl: './combo-type.component.html', + imports: [IgxComboComponent, IgxLabelDirective, IgxPrefixDirective, IgxIconComponent] +}) +export class ComboTypeComponent { + public options: Option[] = [1, 2, 3, 4, 5].map((id) => ({ id, name: 'Item', group: 'Header' })); + + public types: ComboType[] = [ + { label: 'Border Type', type: 'border' }, + { label: 'Box Type', type: 'box' } + ]; + + private combos = viewChildren(IgxComboComponent); + + constructor() { + const element = inject>(ElementRef).nativeElement; + inject(IgxIconService).addSvgIconFromText('language', languageIcon, 'material'); + + // The combos are shown open. Opening a combo moves the focus to its search input, so + // the sample is inert until the combos open and the page keeps its focus. + afterNextRender(() => { + const combos = this.combos(); + element.inert = true; + forkJoin(combos.map((combo) => combo.opened.pipe(take(1)))).subscribe(() => { + element.inert = false; + }); + combos.forEach((combo) => combo.open()); + }); + } +} diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.html b/src/app/lists/combo/combo-validation/combo-validation.component.html new file mode 100644 index 0000000000..c81767a8f2 --- /dev/null +++ b/src/app/lists/combo/combo-validation/combo-validation.component.html @@ -0,0 +1,24 @@ +
+ + @for (state of states; track state.label) { + {{ state.label }} + } + @for (type of types; track type.label) { + {{ type.label }} + @for (state of states; track state.label) { + + @if (state.helperText) { + {{ state.helperText }} + } + + } + } +
diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.scss b/src/app/lists/combo/combo-validation/combo-validation.component.scss new file mode 100644 index 0000000000..f9f40dcc31 --- /dev/null +++ b/src/app/lists/combo/combo-validation/combo-validation.component.scss @@ -0,0 +1,56 @@ +:host { + /* styles.scss asks the page for the large size; the combos keep their own + default medium size here. */ + --ig-size: var(--ig-size-medium); + + display: flex; + align-items: center; + justify-content: center; + height: 100%; + padding: 1rem; +} + +.states { + display: grid; + grid-template-columns: max-content repeat(3, minmax(0, 17.4375rem)); + width: 100%; + justify-content: center; + align-items: start; + column-gap: 1.75rem; + row-gap: 1rem; +} + +.type-label { + padding-top: 0.75rem; +} + +.state-combo { + pointer-events: none; +} + +/* The Material theme leaves the bottom line of a valid box combo uncolored, so the + success combos color it with the success color. */ +@container style(--ig-theme: material) { + .state-combo.success > ::ng-deep igx-input-group .igx-input-group__bundle::before { + border-block-end-color: var(--success-secondary-color); + } +} + +.state-combo.warn > ::ng-deep igx-input-group { + --border-color: var(--warning-secondary-color); + --idle-bottom-line-color: var(--warning-secondary-color); +} + +.state-combo.warn igx-hint { + color: var(--warning-secondary-color); +} + +.state-label { + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); +} + +.state-column { + justify-self: center; +} diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.ts b/src/app/lists/combo/combo-validation/combo-validation.component.ts new file mode 100644 index 0000000000..d182430dd1 --- /dev/null +++ b/src/app/lists/combo/combo-validation/combo-validation.component.ts @@ -0,0 +1,70 @@ +import { ChangeDetectorRef, Component, ElementRef, afterNextRender, inject, viewChildren } from '@angular/core'; +import { IgxComboComponent } from 'igniteui-angular/combo'; +import { IgxHintDirective, IgxInputGroupType, IgxInputState } from 'igniteui-angular/input-group'; + +interface Country { + id: string; + name: string; + region: string; +} + +interface ValidationState { + label: string; + className: string; + state?: IgxInputState; + helperText?: string; +} + +interface ComboType { + label: string; + type: IgxInputGroupType; +} + +@Component({ + selector: 'app-combo-validation', + styleUrls: ['./combo-validation.component.scss'], + templateUrl: './combo-validation.component.html', + imports: [IgxComboComponent, IgxHintDirective] +}) +export class ComboValidationComponent { + public countries: Country[] = [ + { id: 'BY', name: 'Belarus', region: 'Europe' }, + { id: 'BE', name: 'Belgium', region: 'Europe' }, + { id: 'BG', name: 'Bulgaria', region: 'Europe' } + ]; + + // The combo has built-in valid and invalid states, so the `warn` class shows the + // warning state on the display-only combos. + public states: ValidationState[] = [ + { label: 'Success', className: 'success', state: IgxInputState.VALID }, + { label: 'Warn', className: 'warn', helperText: 'Additional fees might be included' }, + { label: 'Error', className: 'error', state: IgxInputState.INVALID, helperText: 'Please select a different region' } + ]; + + public types: ComboType[] = [ + { label: 'Border Type', type: 'border' }, + { label: 'Box Type', type: 'box' } + ]; + + private combos = viewChildren(IgxComboComponent); + private cdr = inject(ChangeDetectorRef); + + constructor() { + // The combos are display-only, so the sample is inert. + inject>(ElementRef).nativeElement.inert = true; + + afterNextRender(() => { + for (const combo of this.combos()) { + combo.select(['BY', 'BE']); + } + this.setStates(); + }); + } + + private setStates() { + this.combos().forEach((combo, index) => { + combo.valid = this.states[index % this.states.length].state ?? IgxInputState.INITIAL; + }); + this.cdr.markForCheck(); + } +} diff --git a/src/app/lists/lists-routes-data.ts b/src/app/lists/lists-routes-data.ts index e2d25c0a23..c6fbc9c228 100644 --- a/src/app/lists/lists-routes-data.ts +++ b/src/app/lists/lists-routes-data.ts @@ -10,6 +10,14 @@ export const listsRoutesData = { 'combo-tailwind-styling': { displayName: 'Combo Tailwind Styling', parentName: 'Combo' }, 'combo-template': { displayName: 'Templating Combo', parentName: 'Combo' }, 'combo-overlay': { displayName: 'Combo Overlay', parentName: 'Combo' }, + 'combo-overview': { displayName: 'Combo Overview', parentName: 'Combo' }, + 'combo-type': { displayName: 'Combo Type', parentName: 'Combo' }, + 'combo-disabled': { displayName: 'Combo Disabled', parentName: 'Combo' }, + 'combo-size': { displayName: 'Combo Size', parentName: 'Combo' }, + 'combo-states': { displayName: 'Combo States', parentName: 'Combo' }, + 'combo-validation': { displayName: 'Combo Validation', parentName: 'Combo' }, + 'combo-dropdown-size': { displayName: 'Combo Dropdown Size', parentName: 'Combo' }, + 'combo-search-input': { displayName: 'Combo Search Input', parentName: 'Combo' }, 'simple-combo-main': { displayName: 'Main Simple Combo', parentName: 'Combo'}, 'simple-combo-usage': { displayName: 'Usage Simple Combo', parentName: 'Combo'}, 'simple-combo-cascading': { displayName: 'Cascading Simple Combo', parentName: 'Combo'}, diff --git a/src/app/lists/lists.routes.ts b/src/app/lists/lists.routes.ts index 3036dba6b7..86c1aaa977 100644 --- a/src/app/lists/lists.routes.ts +++ b/src/app/lists/lists.routes.ts @@ -8,6 +8,14 @@ import { ComboStylingComponent } from './combo/combo-styling/combo-styling.compo import { ComboTailwindStylingComponent } from './combo/combo-tailwind-styling/combo-tailwind-styling.component'; import { ComboValueKeyComponent } from './combo/combo-valuekey/combo-valuekey.component'; import { ComboTemplateComponent } from './combo/combo-template/combo-template.component'; +import { ComboOverviewComponent } from './combo/combo-overview/combo-overview.component'; +import { ComboTypeComponent } from './combo/combo-type/combo-type.component'; +import { ComboDisabledComponent } from './combo/combo-disabled/combo-disabled.component'; +import { ComboSizeComponent } from './combo/combo-size/combo-size.component'; +import { ComboStatesComponent } from './combo/combo-states/combo-states.component'; +import { ComboValidationComponent } from './combo/combo-validation/combo-validation.component'; +import { ComboDropdownSizeComponent } from './combo/combo-dropdown-size/combo-dropdown-size.component'; +import { ComboSearchInputComponent } from './combo/combo-search-input/combo-search-input.component'; import { ListChatSampleComponent } from './list/list-chat-sample/list-chat-sample.component'; import { ListSample1Component } from './list/list-sample-1/list-sample-1.component'; import { ListSample2Component } from './list/list-sample-2/list-sample-2.component'; @@ -77,6 +85,46 @@ export const ListsRoutes: Routes = [ data: listsRoutesData['combo-overlay'], path: 'combo-overlay' }, + { + component: ComboOverviewComponent, + data: listsRoutesData['combo-overview'], + path: 'combo-overview' + }, + { + component: ComboTypeComponent, + data: listsRoutesData['combo-type'], + path: 'combo-type' + }, + { + component: ComboDisabledComponent, + data: listsRoutesData['combo-disabled'], + path: 'combo-disabled' + }, + { + component: ComboSizeComponent, + data: listsRoutesData['combo-size'], + path: 'combo-size' + }, + { + component: ComboStatesComponent, + data: listsRoutesData['combo-states'], + path: 'combo-states' + }, + { + component: ComboValidationComponent, + data: listsRoutesData['combo-validation'], + path: 'combo-validation' + }, + { + component: ComboDropdownSizeComponent, + data: listsRoutesData['combo-dropdown-size'], + path: 'combo-dropdown-size' + }, + { + component: ComboSearchInputComponent, + data: listsRoutesData['combo-search-input'], + path: 'combo-search-input' + }, { component: SimpleComboMainComponent, data: listsRoutesData['simple-combo-main'], From ced2d6699e4c64205afe17cc0db50f310d2f546d Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 11 Nov 2026 15:39:43 +0200 Subject: [PATCH 2/5] fix(combo): update samples content --- .../combo-dropdown-size.component.html | 9 +++++ .../combo-dropdown-size.component.scss | 23 +++++++++++ .../combo-dropdown-size.component.ts | 2 +- .../combo-overview.component.html | 38 ++++++++++++------- .../combo-overview.component.scss | 22 +++++++++++ .../combo-size/combo-size.component.html | 32 ++++++++++------ .../combo-size/combo-size.component.scss | 22 +++++++++++ .../combo-styling.component.html | 33 ++++++++++------ .../combo-styling.component.scss | 22 +++++++++++ .../combo-tailwind-styling.component.html | 33 ++++++++++------ .../combo-type/combo-type.component.html | 9 +++++ .../combo-type/combo-type.component.scss | 22 +++++++++++ .../combo/combo-type/combo-type.component.ts | 2 +- 13 files changed, 220 insertions(+), 49 deletions(-) diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html index 49f28cd3d1..4c43a2a9e1 100644 --- a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html @@ -6,6 +6,7 @@ and a click elsewhere does not close it. --> +
+ Selection + @for (option of combo.selection; track option.id) { + {{ option.name }} + } @empty { + No items selected + } +
} diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss index 4a423025d5..804f769143 100644 --- a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss @@ -28,6 +28,29 @@ display: none; } +/* A dropdown takes no space in the page, so the selection starts below the large dropdown. */ +.selection { + display: flex; + flex-direction: column; + align-self: stretch; + gap: 0.375rem; + margin-top: 14rem; + padding: 0.75rem 1rem; + font: 400 14px / 20px var(--ig-font-family); + letter-spacing: 0.25px; + color: var(--ig-gray-700); +} + +.selection-title { + font-weight: 600; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-900); +} + +.selection-empty { + color: var(--ig-gray-500); +} .small { --ig-size: var(--ig-size-small); diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts index 9dc4370bc7..a63cad1e67 100644 --- a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.ts @@ -21,7 +21,7 @@ interface DropdownSize { imports: [IgxComboComponent] }) export class ComboDropdownSizeComponent { - public options: Option[] = [1, 2, 3].map((id) => ({ id, name: 'Item', group: 'Header' })); + public options: Option[] = [1, 2, 3].map((id) => ({ id, name: `Item ${id}`, group: 'Header' })); public sizes: DropdownSize[] = [ { label: 'Small', className: 'small' }, diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.html b/src/app/lists/combo/combo-overview/combo-overview.component.html index 075b1e708d..62539de7f5 100644 --- a/src/app/lists/combo/combo-overview/combo-overview.component.html +++ b/src/app/lists/combo/combo-overview/combo-overview.component.html @@ -1,14 +1,24 @@ - - - - - - +
+ + + + + + +
+ Selection + @for (city of combo.selection; track city.id) { + {{ city.name }} + } @empty { + No items selected + } +
+
diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.scss b/src/app/lists/combo/combo-overview/combo-overview.component.scss index d38c5d64f5..feec643b7f 100644 --- a/src/app/lists/combo/combo-overview/combo-overview.component.scss +++ b/src/app/lists/combo/combo-overview/combo-overview.component.scss @@ -13,3 +13,25 @@ .locations { width: 22.5rem; } + +.selection { + display: flex; + flex-direction: column; + gap: 0.375rem; + margin-top: 1.625rem; + padding: 0.75rem 1rem; + font: 400 14px / 20px var(--ig-font-family); + letter-spacing: 0.25px; + color: var(--ig-gray-700); +} + +.selection-title { + font-weight: 600; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-900); +} + +.selection-empty { + color: var(--ig-gray-500); +} diff --git a/src/app/lists/combo/combo-size/combo-size.component.html b/src/app/lists/combo/combo-size/combo-size.component.html index 7677e706e0..f611245c4d 100644 --- a/src/app/lists/combo/combo-size/combo-size.component.html +++ b/src/app/lists/combo/combo-size/combo-size.component.html @@ -6,17 +6,27 @@ @for (type of types; track type.label) { {{ type.label }} @for (size of sizes; track size.label) { - - +
+ + +
+ Selection + @for (country of combo.selection; track country.id) { + {{ country.name }} + } @empty { + No items selected + } +
+
} } diff --git a/src/app/lists/combo/combo-size/combo-size.component.scss b/src/app/lists/combo/combo-size/combo-size.component.scss index a89cfd43a3..29dca275b4 100644 --- a/src/app/lists/combo/combo-size/combo-size.component.scss +++ b/src/app/lists/combo/combo-size/combo-size.component.scss @@ -42,3 +42,25 @@ .state-column { justify-self: center; } + +.selection { + display: flex; + flex-direction: column; + gap: 0.375rem; + margin-top: 1.625rem; + padding: 0.75rem 1rem; + font: 400 14px / 20px var(--ig-font-family); + letter-spacing: 0.25px; + color: var(--ig-gray-700); +} + +.selection-title { + font-weight: 600; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-900); +} + +.selection-empty { + color: var(--ig-gray-500); +} diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.html b/src/app/lists/combo/combo-styling/combo-styling.component.html index 0b437c6d1e..09d5f287f7 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.html +++ b/src/app/lists/combo/combo-styling/combo-styling.component.html @@ -1,11 +1,22 @@ - - +
+ + +
+ Selection + @for (country of combo.selection; track country.id) { + {{ country.name }} + } @empty { + No items selected + } +
+
diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.scss b/src/app/lists/combo/combo-styling/combo-styling.component.scss index 6feace04af..640fe6749f 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.scss +++ b/src/app/lists/combo/combo-styling/combo-styling.component.scss @@ -11,6 +11,28 @@ app-combo-styling { justify-content: center; height: 100%; padding: 2rem 1rem; + + .selection { + display: flex; + flex-direction: column; + gap: 0.375rem; + margin-top: 1.625rem; + padding: 0.75rem 1rem; + font: 400 14px / 20px var(--ig-font-family); + letter-spacing: 0.25px; + color: var(--ig-gray-700); + } + + .selection-title { + font-weight: 600; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-900); + } + + .selection-empty { + color: var(--ig-gray-500); + } } .styled-combo { diff --git a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html index 259e0133ff..4873d392f1 100644 --- a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html +++ b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html @@ -1,11 +1,22 @@ - - +
+ + +
+ Selection + @for (country of combo.selection; track country.id) { + {{ country.name }} + } @empty { + No items selected + } +
+
diff --git a/src/app/lists/combo/combo-type/combo-type.component.html b/src/app/lists/combo/combo-type/combo-type.component.html index 5242e11b6c..09a27dbfa4 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.html +++ b/src/app/lists/combo/combo-type/combo-type.component.html @@ -3,6 +3,7 @@
{{ type.label }} +
+ Selection + @for (option of combo.selection; track option.id) { + {{ option.name }} + } @empty { + No items selected + } +
} diff --git a/src/app/lists/combo/combo-type/combo-type.component.scss b/src/app/lists/combo/combo-type/combo-type.component.scss index f45cb9a3d9..df5e65e237 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.scss +++ b/src/app/lists/combo/combo-type/combo-type.component.scss @@ -32,3 +32,25 @@ letter-spacing: 0.3px; color: var(--ig-gray-600); } + +.selection { + display: flex; + flex-direction: column; + gap: 0.375rem; + margin-top: 0.875rem; + padding: 0.75rem 1rem; + font: 400 14px / 20px var(--ig-font-family); + letter-spacing: 0.25px; + color: var(--ig-gray-700); +} + +.selection-title { + font-weight: 600; + line-height: 24px; + letter-spacing: 0.1px; + color: var(--ig-gray-900); +} + +.selection-empty { + color: var(--ig-gray-500); +} diff --git a/src/app/lists/combo/combo-type/combo-type.component.ts b/src/app/lists/combo/combo-type/combo-type.component.ts index dbe0a06be9..ee9ed335a8 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.ts +++ b/src/app/lists/combo/combo-type/combo-type.component.ts @@ -24,7 +24,7 @@ interface ComboType { imports: [IgxComboComponent, IgxLabelDirective, IgxPrefixDirective, IgxIconComponent] }) export class ComboTypeComponent { - public options: Option[] = [1, 2, 3, 4, 5].map((id) => ({ id, name: 'Item', group: 'Header' })); + public options: Option[] = [1, 2, 3, 4, 5].map((id) => ({ id, name: `Item ${id}`, group: 'Header' })); public types: ComboType[] = [ { label: 'Border Type', type: 'border' }, From 01f305e27d6b8a6a67932156af7f94730e8a89b0 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 12 Nov 2026 14:16:16 +0200 Subject: [PATCH 3/5] fix(combo): update samples content --- .../combo-disabled.component.html | 4 +-- .../combo-disabled.component.scss | 9 +++++++ .../combo-dropdown-size.component.scss | 4 +-- .../combo-dropdown-size.component.ts | 2 +- .../combo-search-input.component.scss | 4 +-- .../combo-size/combo-size.component.html | 6 ++--- .../combo-size/combo-size.component.scss | 26 +++++++++++++++++++ .../combo/combo-size/combo-size.component.ts | 17 +++++++++++- .../combo-type/combo-type.component.html | 2 +- .../combo-type/combo-type.component.scss | 24 +++++++++++++++++ .../combo/combo-type/combo-type.component.ts | 19 ++++++++++++-- .../combo-validation.component.html | 6 ++--- .../combo-validation.component.scss | 25 ++++++++++-------- 13 files changed, 120 insertions(+), 28 deletions(-) diff --git a/src/app/lists/combo/combo-disabled/combo-disabled.component.html b/src/app/lists/combo/combo-disabled/combo-disabled.component.html index a37714a5ae..dd82954399 100644 --- a/src/app/lists/combo/combo-disabled/combo-disabled.component.html +++ b/src/app/lists/combo/combo-disabled/combo-disabled.component.html @@ -4,9 +4,9 @@ Disabled @for (row of rows; track $index) { @let groupStart = $index === 2; - {{ row.label }} + {{ row.label }} @for (disabled of [false, true]; track disabled) { -
+
({ id, name: `Item ${id}`, group: 'Header' })); + public options: Option[] = [1, 2, 3].map((id) => ({ id, name: 'Item', group: 'Header' })); public sizes: DropdownSize[] = [ { label: 'Small', className: 'small' }, diff --git a/src/app/lists/combo/combo-search-input/combo-search-input.component.scss b/src/app/lists/combo/combo-search-input/combo-search-input.component.scss index 120955598e..2c9696a108 100644 --- a/src/app/lists/combo/combo-search-input/combo-search-input.component.scss +++ b/src/app/lists/combo/combo-search-input/combo-search-input.component.scss @@ -7,14 +7,14 @@ align-items: flex-start; justify-content: center; height: 100%; - padding: 2rem 1rem; + padding: 2.375rem 1rem 2rem; } .states { display: grid; grid-template-columns: repeat(3, 11.25rem); grid-template-rows: repeat(2, 5.5rem); - column-gap: 1rem; + column-gap: 1.875rem; row-gap: 1rem; } diff --git a/src/app/lists/combo/combo-size/combo-size.component.html b/src/app/lists/combo/combo-size/combo-size.component.html index f611245c4d..095e4504c5 100644 --- a/src/app/lists/combo/combo-size/combo-size.component.html +++ b/src/app/lists/combo/combo-size/combo-size.component.html @@ -1,12 +1,12 @@
- + @for (size of sizes; track size.label) { {{ size.label }} } @for (type of types; track type.label) { - {{ type.label }} + {{ type.label }} @for (size of sizes; track size.label) { -
+
}); constructor() { const element = inject>(ElementRef).nativeElement; + const destroyRef = inject(DestroyRef); // The combos are shown open. Opening a combo moves the focus to its search input, so // the sample is inert until the combos open and the page keeps its focus. @@ -57,6 +59,19 @@ export class ComboSizeComponent { element.inert = false; }); combos.forEach((combo) => combo.open()); + + // A dropdown keeps the place and the width from the moment it opens, and only the + // Material theme shows the box type, so a theme change moves and resizes the combos. + // Each combo then publishes its width for its dropdown, and a window resize makes + // the open dropdowns take their places again. + const observer = new ResizeObserver((entries) => { + for (const { target, contentRect } of entries) { + (target as HTMLElement).style.setProperty('--combo-width', `${contentRect.width}px`); + } + window.dispatchEvent(new Event('resize')); + }); + this.comboElements().forEach((combo) => observer.observe(combo.nativeElement)); + destroyRef.onDestroy(() => observer.disconnect()); }); } } diff --git a/src/app/lists/combo/combo-type/combo-type.component.html b/src/app/lists/combo/combo-type/combo-type.component.html index 09a27dbfa4..9715751737 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.html +++ b/src/app/lists/combo/combo-type/combo-type.component.html @@ -1,6 +1,6 @@
@for (type of types; track type.label) { -
+
{{ type.label }} ({ id, name: `Item ${id}`, group: 'Header' })); + public options: Option[] = [1, 2, 3, 4, 5].map((id) => ({ id, name: 'Item', group: 'Header' })); public types: ComboType[] = [ { label: 'Border Type', type: 'border' }, @@ -32,9 +32,11 @@ export class ComboTypeComponent { ]; private combos = viewChildren(IgxComboComponent); + private comboElements = viewChildren(IgxComboComponent, { read: ElementRef }); constructor() { const element = inject>(ElementRef).nativeElement; + const destroyRef = inject(DestroyRef); inject(IgxIconService).addSvgIconFromText('language', languageIcon, 'material'); // The combos are shown open. Opening a combo moves the focus to its search input, so @@ -46,6 +48,19 @@ export class ComboTypeComponent { element.inert = false; }); combos.forEach((combo) => combo.open()); + + // A dropdown keeps the place and the width from the moment it opens, and only the + // Material theme shows the box type, so a theme change moves and resizes the combos. + // Each combo then publishes its width for its dropdown, and a window resize makes + // the open dropdowns take their places again. + const observer = new ResizeObserver((entries) => { + for (const { target, contentRect } of entries) { + (target as HTMLElement).style.setProperty('--combo-width', `${contentRect.width}px`); + } + window.dispatchEvent(new Event('resize')); + }); + this.comboElements().forEach((combo) => observer.observe(combo.nativeElement)); + destroyRef.onDestroy(() => observer.disconnect()); }); } } diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.html b/src/app/lists/combo/combo-validation/combo-validation.component.html index c81767a8f2..8f1c86a46f 100644 --- a/src/app/lists/combo/combo-validation/combo-validation.component.html +++ b/src/app/lists/combo/combo-validation/combo-validation.component.html @@ -1,13 +1,13 @@
- + @for (state of states; track state.label) { {{ state.label }} } @for (type of types; track type.label) { - {{ type.label }} + {{ type.label }} @for (state of states; track state.label) { ::ng-deep igx-input-group .igx-input-group__bundle::before { - border-block-end-color: var(--success-secondary-color); - } -} .state-combo.warn > ::ng-deep igx-input-group { --border-color: var(--warning-secondary-color); --idle-bottom-line-color: var(--warning-secondary-color); } -.state-combo.warn igx-hint { - color: var(--warning-secondary-color); -} - .state-label { font: 400 13px / 20px "Aktiv Grotesk", sans-serif; letter-spacing: 0.3px; From 3af3fec88bfeb2da751a9843d0838b25f3e3d42f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 12 Nov 2026 15:03:17 +0200 Subject: [PATCH 4/5] fix(combo): update validation states --- .../combo/combo-validation/combo-validation.component.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.scss b/src/app/lists/combo/combo-validation/combo-validation.component.scss index c974140bbf..8e98fafd28 100644 --- a/src/app/lists/combo/combo-validation/combo-validation.component.scss +++ b/src/app/lists/combo/combo-validation/combo-validation.component.scss @@ -42,6 +42,9 @@ pointer-events: none; } +.state-combo.success > ::ng-deep igx-input-group .igx-input-group__bundle::before { + border-block-end-color: var(--success-secondary-color); +} .state-combo.warn > ::ng-deep igx-input-group { --border-color: var(--warning-secondary-color); From 603b3bf9f3d58e7e86804ac5fa74e004b20b0eeb Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 12 Nov 2026 17:19:18 +0200 Subject: [PATCH 5/5] fix(combo): update samples content --- .../combo-disabled/combo-disabled.component.html | 4 ++-- .../combo-dropdown-size.component.html | 4 ++-- .../combo-dropdown-size.component.scss | 13 +++---------- .../combo-overview/combo-overview.component.html | 4 ++-- .../combo-overview/combo-overview.component.scss | 13 +++---------- .../combo-search-input.component.html | 2 +- .../combo-search-input.component.scss | 1 - .../combo-search-input.component.ts | 5 ++--- .../combo/combo-size/combo-size.component.html | 4 ++-- .../combo/combo-size/combo-size.component.scss | 13 +++---------- .../combo/combo-states/combo-states.component.html | 2 +- .../combo/combo-states/combo-states.component.scss | 1 - .../combo/combo-states/combo-states.component.ts | 1 - .../combo-styling/combo-styling.component.html | 4 ++-- .../combo-styling/combo-styling.component.scss | 13 +++---------- .../combo-tailwind-styling.component.html | 8 ++++---- .../combo/combo-type/combo-type.component.html | 4 ++-- .../combo/combo-type/combo-type.component.scss | 14 +++----------- .../combo-validation.component.html | 2 -- .../combo-validation.component.scss | 4 ---- .../combo-validation/combo-validation.component.ts | 4 ++-- 21 files changed, 37 insertions(+), 83 deletions(-) diff --git a/src/app/lists/combo/combo-disabled/combo-disabled.component.html b/src/app/lists/combo/combo-disabled/combo-disabled.component.html index dd82954399..8a03092b03 100644 --- a/src/app/lists/combo/combo-disabled/combo-disabled.component.html +++ b/src/app/lists/combo/combo-disabled/combo-disabled.component.html @@ -3,7 +3,7 @@ Enabled Disabled @for (row of rows; track $index) { - @let groupStart = $index === 2; + @let groupStart = $index > 0 && row.type !== rows[$index - 1].type; {{ row.label }} @for (disabled of [false, true]; track disabled) {
@@ -11,7 +11,7 @@ [type]="row.type" [disabled]="disabled" placeholder="Country" - searchPlaceholder="Search" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search' }" valueKey="id" displayKey="name" groupKey="region" diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html index 4c43a2a9e1..db2a800f85 100644 --- a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.html @@ -7,7 +7,7 @@
diff --git a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss index c76a10c014..01f52de6a2 100644 --- a/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss +++ b/src/app/lists/combo/combo-dropdown-size/combo-dropdown-size.component.scss @@ -36,22 +36,15 @@ gap: 0.375rem; margin-top: 14rem; padding: 0.75rem 1rem; - font: 400 14px / 20px var(--ig-font-family); - letter-spacing: 0.25px; - color: var(--ig-gray-700); + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); } .selection-title { - font-weight: 600; - line-height: 24px; - letter-spacing: 0.1px; color: var(--ig-gray-900); } -.selection-empty { - color: var(--ig-gray-500); -} - .small { --ig-size: var(--ig-size-small); } diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.html b/src/app/lists/combo/combo-overview/combo-overview.component.html index 62539de7f5..c8915e8859 100644 --- a/src/app/lists/combo/combo-overview/combo-overview.component.html +++ b/src/app/lists/combo/combo-overview/combo-overview.component.html @@ -3,7 +3,7 @@ #combo type="border" placeholder="Cities" - searchPlaceholder="Search cities" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search cities' }" valueKey="id" displayKey="name" groupKey="country" @@ -18,7 +18,7 @@ @for (city of combo.selection; track city.id) { {{ city.name }} } @empty { - No items selected + No items selected }
diff --git a/src/app/lists/combo/combo-overview/combo-overview.component.scss b/src/app/lists/combo/combo-overview/combo-overview.component.scss index feec643b7f..76061932af 100644 --- a/src/app/lists/combo/combo-overview/combo-overview.component.scss +++ b/src/app/lists/combo/combo-overview/combo-overview.component.scss @@ -20,18 +20,11 @@ gap: 0.375rem; margin-top: 1.625rem; padding: 0.75rem 1rem; - font: 400 14px / 20px var(--ig-font-family); - letter-spacing: 0.25px; - color: var(--ig-gray-700); + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); } .selection-title { - font-weight: 600; - line-height: 24px; - letter-spacing: 0.1px; color: var(--ig-gray-900); } - -.selection-empty { - color: var(--ig-gray-500); -} diff --git a/src/app/lists/combo/combo-search-input/combo-search-input.component.html b/src/app/lists/combo/combo-search-input/combo-search-input.component.html index 6d1a9d62cc..338c9598cf 100644 --- a/src/app/lists/combo/combo-search-input/combo-search-input.component.html +++ b/src/app/lists/combo/combo-search-input/combo-search-input.component.html @@ -6,7 +6,7 @@ and a click elsewhere does not close it. -->
diff --git a/src/app/lists/combo/combo-size/combo-size.component.scss b/src/app/lists/combo/combo-size/combo-size.component.scss index d5b1732b23..8ba7e2f9ad 100644 --- a/src/app/lists/combo/combo-size/combo-size.component.scss +++ b/src/app/lists/combo/combo-size/combo-size.component.scss @@ -75,18 +75,11 @@ igx-combo ::ng-deep .igx-drop-down { gap: 0.375rem; margin-top: 1.625rem; padding: 0.75rem 1rem; - font: 400 14px / 20px var(--ig-font-family); - letter-spacing: 0.25px; - color: var(--ig-gray-700); + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); } .selection-title { - font-weight: 600; - line-height: 24px; - letter-spacing: 0.1px; color: var(--ig-gray-900); } - -.selection-empty { - color: var(--ig-gray-500); -} diff --git a/src/app/lists/combo/combo-states/combo-states.component.html b/src/app/lists/combo/combo-states/combo-states.component.html index e67c8074b9..98fc346c4a 100644 --- a/src/app/lists/combo/combo-states/combo-states.component.html +++ b/src/app/lists/combo/combo-states/combo-states.component.html @@ -6,7 +6,7 @@ class="state-combo {{ state.className }}" type="border" placeholder="Country" - searchPlaceholder="Search" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search' }" valueKey="id" displayKey="name" groupKey="region" diff --git a/src/app/lists/combo/combo-states/combo-states.component.scss b/src/app/lists/combo/combo-states/combo-states.component.scss index 1e7cbd02a2..53833b92c4 100644 --- a/src/app/lists/combo/combo-states/combo-states.component.scss +++ b/src/app/lists/combo/combo-states/combo-states.component.scss @@ -29,7 +29,6 @@ .state-combo { width: 100%; - pointer-events: none; } /* The open dropdown takes no pointer input either. */ diff --git a/src/app/lists/combo/combo-states/combo-states.component.ts b/src/app/lists/combo/combo-states/combo-states.component.ts index 6c2e8dc297..13ecabf3f4 100644 --- a/src/app/lists/combo/combo-states/combo-states.component.ts +++ b/src/app/lists/combo/combo-states/combo-states.component.ts @@ -50,7 +50,6 @@ export class ComboStatesComponent { // to its search input, and the inert sample also keeps the focus on the page. inject>(ElementRef).nativeElement.inert = true; - // The last combo is shown with its dropdown open. afterNextRender(() => { this.combos() .filter((_, index) => this.states[index].open) diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.html b/src/app/lists/combo/combo-styling/combo-styling.component.html index 09d5f287f7..567ab5d3a3 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.html +++ b/src/app/lists/combo/combo-styling/combo-styling.component.html @@ -4,7 +4,7 @@ class="styled-combo" type="border" placeholder="Country" - searchPlaceholder="Search" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search' }" valueKey="id" displayKey="name" groupKey="region" @@ -16,7 +16,7 @@ @for (country of combo.selection; track country.id) { {{ country.name }} } @empty { - No items selected + No items selected }
diff --git a/src/app/lists/combo/combo-styling/combo-styling.component.scss b/src/app/lists/combo/combo-styling/combo-styling.component.scss index 640fe6749f..6893893382 100644 --- a/src/app/lists/combo/combo-styling/combo-styling.component.scss +++ b/src/app/lists/combo/combo-styling/combo-styling.component.scss @@ -18,21 +18,14 @@ app-combo-styling { gap: 0.375rem; margin-top: 1.625rem; padding: 0.75rem 1rem; - font: 400 14px / 20px var(--ig-font-family); - letter-spacing: 0.25px; - color: var(--ig-gray-700); + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); } .selection-title { - font-weight: 600; - line-height: 24px; - letter-spacing: 0.1px; color: var(--ig-gray-900); } - - .selection-empty { - color: var(--ig-gray-500); - } } .styled-combo { diff --git a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html index 4873d392f1..0ab7ed6d82 100644 --- a/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html +++ b/src/app/lists/combo/combo-tailwind-styling/combo-tailwind-styling.component.html @@ -3,7 +3,7 @@ #combo type="border" placeholder="Country" - searchPlaceholder="Search" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search' }" valueKey="id" displayKey="name" groupKey="region" @@ -11,12 +11,12 @@ [(ngModel)]="selection" class="w-[279px] [--ig-font-family:aktiv-grotesk,sans-serif] [--ig-input-group-border-color:var(--color-combo-border)] [--ig-input-group-hover-border-color:var(--color-combo-border)] [--ig-input-group-focused-border-color:var(--color-combo-border)] [--ig-input-group-filled-text-color:var(--color-combo-ink)] [--ig-input-group-focused-bottom-line-color:var(--color-combo-accent)] [--ig-combo-toggle-button-background:var(--color-combo-toggle)] [--ig-combo-toggle-button-background-focus:var(--color-combo-toggle)] [--ig-combo-toggle-button-background-focus--border:var(--color-combo-toggle)] [--ig-combo-toggle-button-foreground:var(--color-combo-ink)] [--ig-combo-toggle-button-foreground-focus:var(--color-combo-ink)] [--ig-combo-toggle-button-foreground-filled:var(--color-combo-ink)] [--ig-drop-down-elevation:none] [--ig-drop-down-background-color:var(--color-combo-surface)] [--ig-drop-down-header-text-color:var(--color-combo-header)] [--ig-drop-down-item-text-color:var(--color-combo-ink)] [--ig-drop-down-hover-item-background:var(--color-combo-toggle)] [--ig-drop-down-focused-item-background:var(--color-combo-toggle)] [--ig-drop-down-selected-item-background:var(--color-combo-selected)] [--ig-drop-down-selected-item-text-color:#000] [--ig-drop-down-selected-hover-item-background:var(--color-combo-selected)] [--ig-drop-down-selected-hover-item-text-color:#000] [--ig-drop-down-selected-focus-item-background:var(--color-combo-selected)] [--ig-drop-down-selected-focus-item-text-color:#000] [--ig-checkbox-empty-color:var(--color-combo-accent)] [--ig-checkbox-fill-color:var(--color-combo-accent)] [&>igx-input-group_input]:!text-sm [&>igx-input-group_input]:!font-medium [&_.igx-drop-down]:!rounded-t-none [&_.igx-drop-down]:!border [&_.igx-drop-down]:!border-t-0 [&_.igx-drop-down]:!border-[color:var(--color-combo-border)] [&_.igx-drop-down]:!pb-4 [&_.igx-drop-down\_\_item]:!font-medium [&_.igx-combo\_\_search_input]:!font-semibold [&_.igx-combo\_\_search_input]:placeholder:!font-normal"> -
- Selection +
+ Selection @for (country of combo.selection; track country.id) { {{ country.name }} } @empty { - No items selected + No items selected }
diff --git a/src/app/lists/combo/combo-type/combo-type.component.html b/src/app/lists/combo/combo-type/combo-type.component.html index 9715751737..4e4a21c437 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.html +++ b/src/app/lists/combo/combo-type/combo-type.component.html @@ -6,7 +6,7 @@ #combo [type]="type.type" placeholder="Select a value" - searchPlaceholder="Search" + [resourceStrings]="{ igx_combo_filter_search_placeholder: 'Search' }" valueKey="id" displayKey="name" groupKey="group" @@ -22,7 +22,7 @@ @for (option of combo.selection; track option.id) { {{ option.name }} } @empty { - No items selected + No items selected }
diff --git a/src/app/lists/combo/combo-type/combo-type.component.scss b/src/app/lists/combo/combo-type/combo-type.component.scss index c15c4abc5b..c158c67d80 100644 --- a/src/app/lists/combo/combo-type/combo-type.component.scss +++ b/src/app/lists/combo/combo-type/combo-type.component.scss @@ -27,7 +27,6 @@ } .type-label { - justify-self: center; text-align: center; font: 400 13px / 20px "Aktiv Grotesk", sans-serif; letter-spacing: 0.3px; @@ -63,18 +62,11 @@ igx-combo ::ng-deep .igx-drop-down { gap: 0.375rem; margin-top: 0.875rem; padding: 0.75rem 1rem; - font: 400 14px / 20px var(--ig-font-family); - letter-spacing: 0.25px; - color: var(--ig-gray-700); + font: 400 13px / 20px "Aktiv Grotesk", sans-serif; + letter-spacing: 0.3px; + color: var(--ig-gray-600); } .selection-title { - font-weight: 600; - line-height: 24px; - letter-spacing: 0.1px; color: var(--ig-gray-900); } - -.selection-empty { - color: var(--ig-gray-500); -} diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.html b/src/app/lists/combo/combo-validation/combo-validation.component.html index 8f1c86a46f..033c9a6967 100644 --- a/src/app/lists/combo/combo-validation/combo-validation.component.html +++ b/src/app/lists/combo/combo-validation/combo-validation.component.html @@ -10,10 +10,8 @@ class="state-combo {{ state.className }} {{ type.type }}-type" [type]="type.type" placeholder="Country" - searchPlaceholder="Search" valueKey="id" displayKey="name" - groupKey="region" [data]="countries"> @if (state.helperText) { {{ state.helperText }} diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.scss b/src/app/lists/combo/combo-validation/combo-validation.component.scss index 8e98fafd28..33f559645e 100644 --- a/src/app/lists/combo/combo-validation/combo-validation.component.scss +++ b/src/app/lists/combo/combo-validation/combo-validation.component.scss @@ -38,10 +38,6 @@ } } -.state-combo { - pointer-events: none; -} - .state-combo.success > ::ng-deep igx-input-group .igx-input-group__bundle::before { border-block-end-color: var(--success-secondary-color); } diff --git a/src/app/lists/combo/combo-validation/combo-validation.component.ts b/src/app/lists/combo/combo-validation/combo-validation.component.ts index d182430dd1..72bb7fd1aa 100644 --- a/src/app/lists/combo/combo-validation/combo-validation.component.ts +++ b/src/app/lists/combo/combo-validation/combo-validation.component.ts @@ -33,8 +33,8 @@ export class ComboValidationComponent { { id: 'BG', name: 'Bulgaria', region: 'Europe' } ]; - // The combo has built-in valid and invalid states, so the `warn` class shows the - // warning state on the display-only combos. + // The combo has built-in valid and invalid states but no warning state, so the `warn` class + // shows it; the `success` class colors the bottom line of the valid state. public states: ValidationState[] = [ { label: 'Success', className: 'success', state: IgxInputState.VALID }, { label: 'Warn', className: 'warn', helperText: 'Additional fees might be included' },