Skip to content

Commit 06f5bbf

Browse files
ZoicanDenisUisergiubologa
authored andcommitted
feat(suggest): use CDK Layout to display the dropdown
1 parent a04667d commit 06f5bbf

File tree

13 files changed

+543
-417
lines changed

13 files changed

+543
-417
lines changed

projects/angular/components/ui-suggest/src/_ui-suggest.theme.scss

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@
2121
}
2222
}
2323

24-
#{$componentName} {
25-
.item-list-container {
26-
background-color: map-get($background, "dialog");
27-
.mat-list {
28-
&-item {
29-
&.selected {
30-
background-color: map-get($background, "disabled-button");
31-
}
24+
.ui-suggest-dropdown-item-list-container {
25+
background-color: map-get($background, "dialog");
26+
.mat-list {
27+
&-item {
28+
&.selected {
29+
background-color: map-get($background, "disabled-button");
30+
}
3231

33-
&.selected.active,
34-
&.active,
35-
&:hover,
36-
&.selected:hover {
37-
background-color: map-get($background, "hover");
38-
}
32+
&.selected.active,
33+
&.active,
34+
&:hover,
35+
&.selected:hover {
36+
background-color: map-get($background, "hover");
3937
}
4038
}
4139
}
40+
}
4241

42+
#{$componentName} {
4343
.display {
4444
mat-icon {
4545
color: inherit;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**
22
* Dropdown direction type definition.
33
*
4+
* default: 'down'
5+
*
46
* @export
57
*/
68
export type SuggestDirection = 'up' | 'down';

projects/angular/components/ui-suggest/src/test/ui-suggest-assert.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ export class UiSuggestAssert {
3535
expect(combo).toHaveAttr('aria-expanded', expectedIsOpen.toString());
3636
}
3737

38-
const itemList = this._root.query(By.css('.item-list-container'));
39-
const itemListClasses = itemList.nativeElement.classList;
40-
expect(itemListClasses.contains('item-list-container-state-open')).toBe(expectedIsOpen);
41-
expect(itemListClasses.contains('item-list-container-state-closed')).toBe(!expectedIsOpen);
38+
const dropdownOverlay = document.querySelector('.cdk-overlay-container');
39+
const itemList = dropdownOverlay?.querySelector('.ui-suggest-dropdown-item-list-container');
40+
expect(!!itemList).toBe(expectedIsOpen);
4241
}
4342

4443
private _assertDisableState(expected: 'enabled' | 'disabled'): void {

projects/angular/components/ui-suggest/src/ui-suggest.animations.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@ export const UI_SUGGEST_ANIMATIONS: {
1919
readonly transformMenuList: AnimationTriggerMetadata;
2020
} = {
2121
transformMenuList: trigger('displayState', [
22-
state('closed', style({
23-
opacity: 0,
24-
transform: 'scale(0.8)',
25-
})),
26-
transition('closed => open', group([
27-
animate('100ms linear', style({
28-
opacity: 1,
29-
})),
30-
animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
31-
transform: 'scale(1)',
32-
})),
33-
])),
34-
transition('* => closed', animate('100ms 25ms linear', style({ opacity: 0 }))),
22+
state(
23+
'void',
24+
style({
25+
opacity: 0,
26+
transform: 'scale(0.8)',
27+
}),
28+
),
29+
transition(
30+
'void => open',
31+
group([
32+
animate('100ms linear', style({
33+
opacity: 1,
34+
})),
35+
animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
36+
transform: 'scale(1)',
37+
})),
38+
]),
39+
),
3540
]),
3641
};

projects/angular/components/ui-suggest/src/ui-suggest.component.html

Lines changed: 101 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<div *ngLet="focus$ | async as focus"
2-
(uiClickOutside)="focused && close(false)"
32
[style.height]="expandInline ? '100%' : undefined"
3+
#optionsDropdownTrigger="cdkOverlayOrigin"
4+
#suggestContainer
5+
cdkOverlayOrigin
46
class="ui-suggest-container"
57
role="application">
68
<!--
@@ -138,106 +140,114 @@
138140
</ng-template>
139141
</ng-container>
140142

143+
<ng-container *ngIf="!expandInline; else optionsDropdown">
144+
<ng-template cdkConnectedOverlay
145+
cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
146+
[cdkConnectedOverlayOrigin]="optionsDropdownTrigger"
147+
[cdkConnectedOverlayPositions]="dropdownPosition"
148+
[cdkConnectedOverlayHasBackdrop]="true"
149+
[cdkConnectedOverlayOpen]="isOpen"
150+
(backdropClick)="close(false)">
151+
<ng-container *ngTemplateOutlet="optionsDropdown">
152+
</ng-container>
153+
</ng-template>
154+
</ng-container>
141155

142-
<div class="item-list-container-wrapper"
143-
[class.multi-select]="multiple && !expandInline"
144-
[style.height]="expandInline ? '100%' : undefined">
145-
<div [style.width]="isFormControl ? null : width"
146-
[style.height]="expandInline ? '100%' : undefined"
147-
[class.item-list-container-state-open]="isOpen"
148-
[class.item-list-container-state-closed]="!isOpen"
149-
[class.item-list-container-direction-down]="isDown"
150-
[class.item-list-container-direction-up]="!isDown"
151-
[class.item-list-container-expanded-inline]="expandInline"
152-
[class.searchable]="searchable && !multiple"
153-
[class.mat-elevation-z4]="!expandInline"
154-
[uiAutofocus]="!searchable && !multiple"
155-
[refocus]="isOpen && !multiple"
156-
[@displayState]="isOpen ? 'open' : 'closed'"
157-
(keydown.arrowup)="navigate(-1, $event)"
158-
(keydown.arrowdown)="navigate(1, $event)"
159-
(keyup.enter)="preventDefault($event);"
160-
(keydown.enter)="preventDefault($event);
161-
setSelectedItem();"
162-
(keydown.esc)="preventDefault($event)"
163-
(keyup.esc)="preventDefault($event);
164-
close();"
165-
(keydown.tab)="close(false)"
166-
(keydown.shift.tab)="close()"
167-
tabindex="-1"
168-
class="item-list-container">
169-
<ng-container *ngIf="!isDown">
170-
<ng-container *ngTemplateOutlet="searchableCountInfoTmpl"></ng-container>
156+
</div>
171157

172-
<ng-container *ngTemplateOutlet="resultList">
173-
</ng-container>
158+
<ng-template #optionsDropdown>
159+
<div [class.is-form-control]="isFormControl"
160+
[style.width]="isFormControl ? (this.suggestContainerWidth+1)+'px' : width"
161+
[style.height]="expandInline ? '100%' : undefined"
162+
[class.ui-suggest-dropdown-item-list-container-expanded-inline]="expandInline"
163+
[class.searchable]="searchable && !multiple"
164+
[class.mat-elevation-z4]="!expandInline"
165+
[uiAutofocus]="!searchable && !multiple"
166+
[refocus]="isOpen && !multiple"
167+
[@displayState]="'open'"
168+
(keydown.arrowup)="navigate(-1, $event)"
169+
(keydown.arrowdown)="navigate(1, $event)"
170+
(keyup.enter)="preventDefault($event);"
171+
(keydown.enter)="preventDefault($event);
172+
setSelectedItem();"
173+
(keydown.esc)="preventDefault($event)"
174+
(keyup.esc)="preventDefault($event);
175+
close();"
176+
(keydown.tab)="close(false)"
177+
(keydown.shift.tab)="close()"
178+
tabindex="-1"
179+
class="ui-suggest-dropdown-item-list-container">
180+
<ng-container *ngIf="!isDown">
181+
<ng-container *ngTemplateOutlet="searchableCountInfoTmpl"></ng-container>
182+
183+
<ng-container *ngTemplateOutlet="resultList">
174184
</ng-container>
185+
</ng-container>
175186

176-
<mat-form-field *ngIf="searchable && (!multiple || compact)"
177-
floatLabel="never">
178-
<input #searchInput
179-
[placeholder]="isFormControl ? '' : placeholder"
180-
[formControl]="inputControl"
181-
[uiAutofocus]="isOpen &&
182-
searchable"
183-
[attr.maxlength]="maxLength"
184-
[refocus]="isOpen"
185-
selectionLocation="end"
186-
autocomplete="off"
187-
aria-autocomplete="list"
188-
matInput>
187+
<mat-form-field *ngIf="searchable && (!multiple || compact)"
188+
floatLabel="never">
189+
<input #searchInput
190+
[placeholder]="isFormControl ? '' : placeholder"
191+
[formControl]="inputControl"
192+
[uiAutofocus]="isOpen &&
193+
searchable"
194+
[attr.maxlength]="maxLength"
195+
[refocus]="isOpen"
196+
selectionLocation="end"
197+
autocomplete="off"
198+
aria-autocomplete="list"
199+
matInput>
189200

190-
<mat-icon *ngIf="inDrillDownMode"
191-
[matTooltip]="intl.clearSelectionLabel"
192-
(keydown.space)="removeSelection($event)"
193-
(keydown.enter)="removeSelection($event)"
194-
(click)="removeSelection($event)"
195-
matSuffix
196-
tabindex="0"
197-
role="button"
198-
aria-hidden="false"
199-
class="clear">
200-
<svg width="100%"
201-
height="100%"
202-
viewBox="0 0 20 20"
203-
style="color:currentColor;fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
204-
<path d="M6.505 13.498l7-7M13.505 13.5l-7-7"
205-
fill="none"
206-
stroke="currentColor"
207-
stroke-width="2.0011213" />
208-
</svg>
209-
</mat-icon>
201+
<mat-icon *ngIf="inDrillDownMode"
202+
[matTooltip]="intl.clearSelectionLabel"
203+
(keydown.space)="removeSelection($event)"
204+
(keydown.enter)="removeSelection($event)"
205+
(click)="removeSelection($event)"
206+
matSuffix
207+
tabindex="0"
208+
role="button"
209+
aria-hidden="false"
210+
class="clear">
211+
<svg width="100%"
212+
height="100%"
213+
viewBox="0 0 20 20"
214+
style="color:currentColor;fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
215+
<path d="M6.505 13.498l7-7M13.505 13.5l-7-7"
216+
fill="none"
217+
stroke="currentColor"
218+
stroke-width="2.0011213" />
219+
</svg>
220+
</mat-icon>
210221

211-
<mat-icon *ngIf="!drillDown || !searchInput.value"
212-
matSuffix>search</mat-icon>
213-
</mat-form-field>
222+
<mat-icon *ngIf="!drillDown || !searchInput.value"
223+
matSuffix>search</mat-icon>
224+
</mat-form-field>
214225

215-
<ng-container *ngIf="isDown">
216-
<ng-container *ngTemplateOutlet="resultList">
217-
</ng-container>
218-
219-
<ng-container *ngTemplateOutlet="searchableCountInfoTmpl"></ng-container>
226+
<ng-container *ngIf="isDown">
227+
<ng-container *ngTemplateOutlet="resultList">
220228
</ng-container>
221229

222-
<ng-template #searchableCountInfoTmpl>
223-
<mat-list-item *ngIf="items.length &&
224-
(loading$ | async) === false &&
225-
searchableCountInfo?.count === items.length &&
226-
searchable &&
227-
!inputControl.value"
228-
[matTooltip]="searchableCountInfo?.message ?? ''"
229-
[attr.role]="'option'"
230-
matTooltipPosition="right"
231-
class="text-ellipsis item-max-count-info-message">
232-
<mat-divider *ngIf="isDown"></mat-divider>
233-
<mat-icon>info_outline</mat-icon>
234-
<span>{{searchableCountInfo?.message}}</span>
235-
<mat-divider *ngIf="!isDown"></mat-divider>
236-
</mat-list-item>
237-
</ng-template>
238-
</div>
230+
<ng-container *ngTemplateOutlet="searchableCountInfoTmpl"></ng-container>
231+
</ng-container>
232+
233+
<ng-template #searchableCountInfoTmpl>
234+
<mat-list-item *ngIf="items.length &&
235+
(loading$ | async) === false &&
236+
searchableCountInfo?.count === items.length &&
237+
searchable &&
238+
!inputControl.value"
239+
[matTooltip]="searchableCountInfo?.message ?? ''"
240+
[attr.role]="'option'"
241+
matTooltipPosition="right"
242+
class="text-ellipsis item-max-count-info-message">
243+
<mat-divider *ngIf="isDown"></mat-divider>
244+
<mat-icon>info_outline</mat-icon>
245+
<span>{{searchableCountInfo?.message}}</span>
246+
<mat-divider *ngIf="!isDown"></mat-divider>
247+
</mat-list-item>
248+
</ng-template>
239249
</div>
240-
</div>
250+
</ng-template>
241251

242252
<ng-template #resultList>
243253
<mat-list [attr.role]="'listbox'"

0 commit comments

Comments
 (0)