Skip to content

Commit d2a7e7a

Browse files
feat: metric card component (#1523)
1 parent e1ce656 commit d2a7e7a

File tree

8 files changed

+151
-0
lines changed

8 files changed

+151
-0
lines changed

projects/assets-library/assets/styles/_color-palette.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ $cloud-3: #a1c5e0;
8484

8585
$brown-1: #9e4c41;
8686

87+
$off-white: #f6f6f64d;
88+
8789
/*
8890
* Specific Usage
8991
*

projects/common/src/color/color.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ export const enum Color {
2525
Gray7 = '#272c2e',
2626
Gray8 = '#171a1c',
2727
Gray9 = '#080909',
28+
Green1 = '#f0fcf6',
2829
Green2 = '#c3f3db',
2930
Green3 = '#95eabe',
31+
Green4 = '#59de99',
3032
Green5 = '#27C675',
3133
Green6 = '#1f9e5c',
34+
Green7 = '#187746',
35+
Green8 = '#10512f',
36+
Green9 = '#03110a',
3237
Orange1 = '#FFF4EB',
3338
Orange3 = '#FDC088',
3439
Orange4 = '#fca555',
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
@import 'mixins';
2+
3+
.metric-card {
4+
display: flex;
5+
flex-direction: column;
6+
gap: 4px;
7+
border: 1px solid;
8+
padding: 10px;
9+
border-radius: 6px;
10+
11+
.indicator-and-title {
12+
display: flex;
13+
align-items: center;
14+
gap: 6px;
15+
16+
.indicator {
17+
.dot {
18+
width: 8px;
19+
height: 8px;
20+
border-radius: 50%;
21+
}
22+
}
23+
24+
.title-text {
25+
@include chart-small-regular($gray-7);
26+
text-transform: uppercase;
27+
}
28+
}
29+
30+
.value {
31+
@include header-5($gray-7);
32+
margin-left: 14px;
33+
}
34+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { IconType } from '@hypertrace/assets-library';
2+
import { createComponentFactory } from '@ngneat/spectator/jest';
3+
import { MockComponent } from 'ng-mocks';
4+
import { IconComponent } from '../icon/icon.component';
5+
import { MetricCardIndicatorType } from './metric-card';
6+
import { MetricCardComponent } from './metric-card.component';
7+
8+
describe('Metric Card Component', () => {
9+
const createComponent = createComponentFactory({
10+
component: MetricCardComponent,
11+
declarations: [MockComponent(IconComponent)],
12+
shallow: true
13+
});
14+
15+
test('should render everything correctly', () => {
16+
const spectator = createComponent({
17+
props: {
18+
value: 123
19+
}
20+
});
21+
22+
expect(spectator.query('.metric-card')).toExist();
23+
expect(spectator.query('.dot')).toExist();
24+
expect(spectator.query('.value')).toHaveText('123');
25+
expect(spectator.query(IconComponent)).not.toExist();
26+
27+
spectator.setInput({
28+
icon: IconType.Add,
29+
indicator: MetricCardIndicatorType.Icon
30+
});
31+
32+
expect(spectator.query('.dot')).not.toExist();
33+
expect(spectator.query(IconComponent)).toExist();
34+
});
35+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2+
import { Color } from '@hypertrace/common';
3+
import { IconSize } from '../icon/icon-size';
4+
import { MetricCardIndicatorType } from './metric-card';
5+
@Component({
6+
selector: 'ht-metric-card',
7+
styleUrls: ['./metric-card.component.scss'],
8+
changeDetection: ChangeDetectionStrategy.OnPush,
9+
template: `
10+
<div class="metric-card" [style.backgroundColor]="this.backgroundColor" [style.borderColor]="this.borderColor">
11+
<div class="indicator-and-title">
12+
<div class="indicator">
13+
<ng-container [ngSwitch]="this.indicator">
14+
<ng-container *ngSwitchCase="'${MetricCardIndicatorType.Dot}'">
15+
<div class="dot" [style.backgroundColor]="this.indicatorColor"></div>
16+
</ng-container>
17+
<ng-container *ngSwitchCase="'${MetricCardIndicatorType.Icon}'">
18+
<ht-icon
19+
*ngIf="this.icon"
20+
class="icon"
21+
[icon]="this.icon"
22+
size="${IconSize.Small}"
23+
[color]="this.indicatorColor"
24+
></ht-icon>
25+
</ng-container>
26+
</ng-container>
27+
</div>
28+
<div class="title-text">{{ this.titleText }}</div>
29+
</div>
30+
<div class="value">{{ value }}</div>
31+
</div>
32+
`
33+
})
34+
export class MetricCardComponent {
35+
@Input()
36+
public titleText?: string;
37+
38+
@Input()
39+
public value?: string | number;
40+
41+
@Input()
42+
public indicator: MetricCardIndicatorType = MetricCardIndicatorType.Dot;
43+
44+
@Input()
45+
public icon?: string; // Only be used when indicator type is Icon
46+
47+
@Input()
48+
public indicatorColor: Color = Color.Gray7;
49+
50+
@Input()
51+
public backgroundColor: Color = Color.OffWhite;
52+
53+
@Input()
54+
public borderColor: Color = Color.Transparent;
55+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { CommonModule } from '@angular/common';
2+
import { NgModule } from '@angular/core';
3+
import { IconModule } from '../icon/icon.module';
4+
import { MetricCardComponent } from './metric-card.component';
5+
6+
@NgModule({
7+
imports: [CommonModule, IconModule],
8+
declarations: [MetricCardComponent],
9+
exports: [MetricCardComponent]
10+
})
11+
export class MetricCardModule {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const enum MetricCardIndicatorType {
2+
Dot = 'dot',
3+
Icon = 'icon'
4+
}

projects/components/src/public-api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ export * from './load-async/load-async-state.type';
199199
export { MessageDisplayComponent } from './message-display/message-display.component';
200200
export { MessageDisplayModule } from './message-display/message-display.module';
201201

202+
// Metric Card
203+
export * from './metric-card/metric-card';
204+
export * from './metric-card/metric-card.component';
205+
export * from './metric-card/metric-card.module';
206+
202207
// Modal
203208
export * from './modal/modal';
204209
export * from './modal/modal.module';

0 commit comments

Comments
 (0)