diff --git a/projects/assets-library/assets/styles/_color-palette.scss b/projects/assets-library/assets/styles/_color-palette.scss index 1905c6594..186497312 100644 --- a/projects/assets-library/assets/styles/_color-palette.scss +++ b/projects/assets-library/assets/styles/_color-palette.scss @@ -84,6 +84,8 @@ $cloud-3: #a1c5e0; $brown-1: #9e4c41; +$off-white: #f6f6f64d; + /* * Specific Usage * diff --git a/projects/common/src/color/color.ts b/projects/common/src/color/color.ts index 3e5b44eab..859ddc604 100644 --- a/projects/common/src/color/color.ts +++ b/projects/common/src/color/color.ts @@ -25,10 +25,15 @@ export const enum Color { Gray7 = '#272c2e', Gray8 = '#171a1c', Gray9 = '#080909', + Green1 = '#f0fcf6', Green2 = '#c3f3db', Green3 = '#95eabe', + Green4 = '#59de99', Green5 = '#27C675', Green6 = '#1f9e5c', + Green7 = '#187746', + Green8 = '#10512f', + Green9 = '#03110a', Orange1 = '#FFF4EB', Orange3 = '#FDC088', Orange4 = '#fca555', diff --git a/projects/components/src/metric-card/metric-card.component.scss b/projects/components/src/metric-card/metric-card.component.scss new file mode 100644 index 000000000..f38fb8785 --- /dev/null +++ b/projects/components/src/metric-card/metric-card.component.scss @@ -0,0 +1,34 @@ +@import 'mixins'; + +.metric-card { + display: flex; + flex-direction: column; + gap: 4px; + border: 1px solid; + padding: 10px; + border-radius: 6px; + + .indicator-and-title { + display: flex; + align-items: center; + gap: 6px; + + .indicator { + .dot { + width: 8px; + height: 8px; + border-radius: 50%; + } + } + + .title-text { + @include chart-small-regular($gray-7); + text-transform: uppercase; + } + } + + .value { + @include header-5($gray-7); + margin-left: 14px; + } +} diff --git a/projects/components/src/metric-card/metric-card.component.test.ts b/projects/components/src/metric-card/metric-card.component.test.ts new file mode 100644 index 000000000..bc36f95e3 --- /dev/null +++ b/projects/components/src/metric-card/metric-card.component.test.ts @@ -0,0 +1,35 @@ +import { IconType } from '@hypertrace/assets-library'; +import { createComponentFactory } from '@ngneat/spectator/jest'; +import { MockComponent } from 'ng-mocks'; +import { IconComponent } from '../icon/icon.component'; +import { MetricCardIndicatorType } from './metric-card'; +import { MetricCardComponent } from './metric-card.component'; + +describe('Metric Card Component', () => { + const createComponent = createComponentFactory({ + component: MetricCardComponent, + declarations: [MockComponent(IconComponent)], + shallow: true + }); + + test('should render everything correctly', () => { + const spectator = createComponent({ + props: { + value: 123 + } + }); + + expect(spectator.query('.metric-card')).toExist(); + expect(spectator.query('.dot')).toExist(); + expect(spectator.query('.value')).toHaveText('123'); + expect(spectator.query(IconComponent)).not.toExist(); + + spectator.setInput({ + icon: IconType.Add, + indicator: MetricCardIndicatorType.Icon + }); + + expect(spectator.query('.dot')).not.toExist(); + expect(spectator.query(IconComponent)).toExist(); + }); +}); diff --git a/projects/components/src/metric-card/metric-card.component.ts b/projects/components/src/metric-card/metric-card.component.ts new file mode 100644 index 000000000..033629333 --- /dev/null +++ b/projects/components/src/metric-card/metric-card.component.ts @@ -0,0 +1,55 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { Color } from '@hypertrace/common'; +import { IconSize } from '../icon/icon-size'; +import { MetricCardIndicatorType } from './metric-card'; +@Component({ + selector: 'ht-metric-card', + styleUrls: ['./metric-card.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` +
+
+
+ + +
+
+ + + +
+
+
{{ this.titleText }}
+
+
{{ value }}
+
+ ` +}) +export class MetricCardComponent { + @Input() + public titleText?: string; + + @Input() + public value?: string | number; + + @Input() + public indicator: MetricCardIndicatorType = MetricCardIndicatorType.Dot; + + @Input() + public icon?: string; // Only be used when indicator type is Icon + + @Input() + public indicatorColor: Color = Color.Gray7; + + @Input() + public backgroundColor: Color = Color.OffWhite; + + @Input() + public borderColor: Color = Color.Transparent; +} diff --git a/projects/components/src/metric-card/metric-card.module.ts b/projects/components/src/metric-card/metric-card.module.ts new file mode 100644 index 000000000..0809f7737 --- /dev/null +++ b/projects/components/src/metric-card/metric-card.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { IconModule } from '../icon/icon.module'; +import { MetricCardComponent } from './metric-card.component'; + +@NgModule({ + imports: [CommonModule, IconModule], + declarations: [MetricCardComponent], + exports: [MetricCardComponent] +}) +export class MetricCardModule {} diff --git a/projects/components/src/metric-card/metric-card.ts b/projects/components/src/metric-card/metric-card.ts new file mode 100644 index 000000000..113291332 --- /dev/null +++ b/projects/components/src/metric-card/metric-card.ts @@ -0,0 +1,4 @@ +export const enum MetricCardIndicatorType { + Dot = 'dot', + Icon = 'icon' +} diff --git a/projects/components/src/public-api.ts b/projects/components/src/public-api.ts index fc183c97c..aed9b32c7 100644 --- a/projects/components/src/public-api.ts +++ b/projects/components/src/public-api.ts @@ -199,6 +199,11 @@ export * from './load-async/load-async-state.type'; export { MessageDisplayComponent } from './message-display/message-display.component'; export { MessageDisplayModule } from './message-display/message-display.module'; +// Metric Card +export * from './metric-card/metric-card'; +export * from './metric-card/metric-card.component'; +export * from './metric-card/metric-card.module'; + // Modal export * from './modal/modal'; export * from './modal/modal.module';