Skip to content

Commit 80fcc29

Browse files
authored
refactor: styling changes on select and multi select (#1439)
* refactor: styling changes on select and multi select * refactor: keep default triggerDisplayMode as undefined * revert: menu with border should be default
1 parent d2cea35 commit 80fcc29

File tree

6 files changed

+74
-10
lines changed

6 files changed

+74
-10
lines changed

projects/components/src/multi-select/multi-select.component.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
}
3636

3737
&.extra-small {
38-
height: 30px;
38+
height: 24px;
3939
}
4040

4141
&.small {
@@ -98,6 +98,10 @@
9898
&:hover {
9999
background-color: $gray-1;
100100
}
101+
102+
&.menu-with-background {
103+
background-color: $gray-1;
104+
}
101105
}
102106
}
103107

projects/components/src/multi-select/multi-select.component.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { IconSize } from '../icon/icon-size';
2020
import { SearchBoxDisplayMode } from '../search-box/search-box.component';
2121
import { SelectOptionComponent } from '../select/select-option.component';
2222
import { SelectSize } from '../select/select-size';
23+
import { SelectTriggerDisplayMode } from '../select/select.component';
2324
import { MultiSelectJustify } from './multi-select-justify';
2425
@Component({
2526
selector: 'ht-multi-select',
@@ -57,7 +58,8 @@ import { MultiSelectJustify } from './multi-select-justify';
5758
this.triggerLabelDisplayMode,
5859
this.popoverOpen ? 'open' : '',
5960
this.size,
60-
this.disabled ? 'disabled' : ''
61+
this.disabled ? 'disabled' : '',
62+
this.triggerDisplayMode
6163
]"
6264
#triggerContainer
6365
>
@@ -171,6 +173,9 @@ export class MultiSelectComponent<V> implements ControlValueAccessor, AfterConte
171173
@Input()
172174
public justify: MultiSelectJustify = MultiSelectJustify.Left;
173175

176+
@Input()
177+
public triggerDisplayMode?: SelectTriggerDisplayMode = SelectTriggerDisplayMode.MenuWithBorder;
178+
174179
@Input()
175180
public triggerLabelDisplayMode: TriggerLabelDisplayMode = TriggerLabelDisplayMode.Selection;
176181

@@ -251,7 +256,7 @@ export class MultiSelectComponent<V> implements ControlValueAccessor, AfterConte
251256
}
252257

253258
public isSelectedItem(item: SelectOptionComponent<V>): boolean {
254-
return this.selected !== undefined && this.selected.filter(value => isEqual(value, item.value)).length > 0;
259+
return Array.isArray(this.selected) && this.selected.filter(value => isEqual(value, item.value)).length > 0;
255260
}
256261

257262
public preventClickDefault(event: Event): void {

projects/components/src/select/select.component.scss

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
width: 100%;
1919
height: 36px;
2020

21+
&.extra-small {
22+
height: 24px;
23+
}
24+
2125
&.small {
2226
height: 32px;
2327
}
@@ -64,7 +68,7 @@
6468
.trigger-content {
6569
display: flex;
6670
align-items: center;
67-
padding: 0 8px;
71+
padding-left: 8px;
6872
height: 100%;
6973

7074
&.menu-with-border {
@@ -78,7 +82,7 @@
7882
border-radius: 4px;
7983

8084
.trigger-label {
81-
@include body-1-medium($gray-9);
85+
@include body-2-medium();
8286
}
8387

8488
.trigger-icon {
@@ -154,6 +158,8 @@
154158
.select-content {
155159
@include dropdown();
156160
max-height: 204px;
161+
display: flex;
162+
flex-direction: column;
157163

158164
.select-option {
159165
display: flex;
@@ -201,3 +207,16 @@
201207
}
202208
}
203209
}
210+
211+
.search-bar {
212+
display: flex;
213+
height: 34px;
214+
margin-top: 2px;
215+
cursor: pointer;
216+
font-size: 14px;
217+
align-items: center;
218+
}
219+
220+
.divider {
221+
padding: 0 16px;
222+
}

projects/components/src/select/select.component.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import {
1313
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
1414
import { IconType } from '@hypertrace/assets-library';
1515
import { LoggerService, queryListAndChanges$, SubscriptionLifecycle, TypedSimpleChanges } from '@hypertrace/common';
16+
import { isEqual } from 'lodash-es';
1617
import { EMPTY, merge, Observable, of } from 'rxjs';
1718
import { map, switchMap } from 'rxjs/operators';
1819
import { IconSize } from '../icon/icon-size';
20+
import { SearchBoxDisplayMode } from '../search-box/search-box.component';
1921
import { SelectControlOptionComponent, SelectControlOptionPosition } from './select-control-option.component';
2022
import { SelectGroupPosition } from './select-group-position';
2123
import { SelectJustify } from './select-justify';
@@ -115,12 +117,23 @@ import { SelectSize } from './select-size';
115117
>
116118
</ht-label
117119
></ng-template>
118-
<ht-icon class="trigger-icon" icon="${IconType.ChevronDown}" size="${IconSize.Small}"> </ht-icon>
120+
<ht-icon class="trigger-icon" icon="${IconType.ChevronDown}" size="${IconSize.ExtraSmall}"> </ht-icon>
119121
</div>
120122
</div>
121123
</ht-popover-trigger>
122124
<ht-popover-content>
123125
<div class="select-content" [ngStyle]="{ 'minWidth.px': triggerContainer.offsetWidth }">
126+
<ng-container *ngIf="this.searchMode === '${SelectSearchMode.EmitOnly}'">
127+
<ht-event-blocker event="click" [enabled]="true">
128+
<ht-search-box
129+
class="search-bar"
130+
(valueChange)="this.searchOptions($event)"
131+
[debounceTime]="200"
132+
displayMode="${SearchBoxDisplayMode.NoBorder}"
133+
></ht-search-box>
134+
</ht-event-blocker>
135+
<ht-divider class="divider"></ht-divider>
136+
</ng-container>
124137
<ng-container *htLetAsync="this.topControlItems$ as topControlItems">
125138
<div *ngIf="topControlItems?.length !== 0">
126139
<ng-container
@@ -206,9 +219,15 @@ export class SelectComponent<V> implements ControlValueAccessor, AfterContentIni
206219
@Input()
207220
public highlightSelected: boolean = true;
208221

222+
@Input()
223+
public searchMode: SelectSearchMode = SelectSearchMode.Disabled;
224+
209225
@Output()
210226
public readonly selectedChange: EventEmitter<V> = new EventEmitter<V>();
211227

228+
@Output()
229+
public readonly searchValueChange: EventEmitter<string> = new EventEmitter<string>();
230+
212231
@ContentChildren(SelectOptionComponent)
213232
public items?: QueryList<SelectOptionComponent<V>>;
214233

@@ -258,14 +277,22 @@ export class SelectComponent<V> implements ControlValueAccessor, AfterContentIni
258277
}
259278

260279
public isSelectedItem(item: SelectOptionComponent<V>): boolean {
261-
return this.selected === item.value;
280+
return isEqual(this.selected, item.value);
262281
}
263282

264283
public updateGroupPosition(position: SelectGroupPosition): void {
265284
this.groupPosition = position;
266285
this.changeDetector.markForCheck();
267286
}
268287

288+
public searchOptions(searchText: string): void {
289+
if (this.searchMode === SelectSearchMode.Disabled) {
290+
return;
291+
}
292+
293+
this.searchValueChange.emit(searchText);
294+
}
295+
269296
private buildObservableOfSelected(): Observable<SelectOption<V> | undefined> {
270297
if (!this.items) {
271298
return EMPTY;
@@ -339,3 +366,8 @@ export const enum SelectTriggerDisplayMode {
339366
MenuWithBackground = 'menu-with-background',
340367
Icon = 'icon'
341368
}
369+
370+
export const enum SelectSearchMode {
371+
Disabled = 'disabled', // Search is not available
372+
EmitOnly = 'emit-only' // Current available values not filtered, but an emit still triggered
373+
}

projects/components/src/select/select.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { NgModule } from '@angular/core';
33
import { FormsModule } from '@angular/forms';
44
import { MemoizeModule } from '@hypertrace/common';
55
import { DividerModule } from '../divider/divider.module';
6+
import { EventBlockerModule } from '../event-blocker/event-blocker.module';
67
import { IconModule } from '../icon/icon.module';
78
import { LabelModule } from '../label/label.module';
89
import { LetAsyncModule } from '../let-async/let-async.module';
910
import { PopoverModule } from '../popover/popover.module';
11+
import { TraceSearchBoxModule } from '../search-box/search-box.module';
1012
import { TooltipModule } from '../tooltip/tooltip.module';
1113
import { SelectOptionRendererDirective } from './directive/select-option-renderer.directive';
1214
import { SelectControlOptionComponent } from './select-control-option.component';
@@ -24,7 +26,9 @@ import { SelectComponent } from './select.component';
2426
PopoverModule,
2527
TooltipModule,
2628
DividerModule,
27-
MemoizeModule
29+
MemoizeModule,
30+
TraceSearchBoxModule,
31+
EventBlockerModule
2832
],
2933
declarations: [
3034
SelectComponent,

projects/observability/src/shared/services/filter-builder/graphql-filter-builder.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import { assertUnreachable } from '@hypertrace/common';
3-
import { FieldFilter, FilterOperator, FilterValue, TableFilter } from '@hypertrace/components';
3+
import { FieldFilter, Filter, FilterOperator, FilterValue, TableFilter } from '@hypertrace/components';
44
import { GraphQlArgumentValue } from '@hypertrace/graphql-client';
55
import { GraphQlFieldFilter } from '../../graphql/model/schema/filter/field/graphql-field-filter';
66
import { GraphQlFilter, GraphQlOperatorType } from '../../graphql/model/schema/filter/graphql-filter';
@@ -20,7 +20,7 @@ export class GraphQlFilterBuilderService {
2020
}));
2121
}
2222

23-
public buildGraphQlFieldFilters(filters: FieldFilter[]): GraphQlFieldFilter[] {
23+
public buildGraphQlFieldFilters(filters: (Filter | FieldFilter)[]): GraphQlFieldFilter[] {
2424
return filters.map(
2525
filter =>
2626
new GraphQlFieldFilter(

0 commit comments

Comments
 (0)