Skip to content

Commit

Permalink
New variations to indicators (#619)
Browse files Browse the repository at this point in the history
* chore: initial commit

* feat: add skeleton component

* chore: add skeleton unit tests

* style: using variables

* chore: update imports

* style: improve animation and update story

* chore: fix typo

* chore: apply corrections suggested by @iurynogueira

* feat: add load and preview states ✨

* feat: add indicator error state ✨

---------

Co-authored-by: Yur16 <[email protected]>
Co-authored-by: Alysson Keysson <[email protected]>
  • Loading branch information
3 people authored May 3, 2023
1 parent 3dcd994 commit 8eb06b7
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 34 deletions.
3 changes: 3 additions & 0 deletions projects/ion/src/lib/core/types/indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export interface IonIndicatorProps {
value?: string | number;
secondValue?: string | number;
buttonConfig?: IonIndicatorButtonConfiguration;
preview?: boolean;
loading?: boolean;
error?: boolean;
}

export interface IonIndicatorButtonConfiguration {
Expand Down
89 changes: 58 additions & 31 deletions projects/ion/src/lib/indicator/indicator.component.html
Original file line number Diff line number Diff line change
@@ -1,35 +1,62 @@
<div data-testid="ion-indicator" class="container">
<header class="title">
<h1 data-testid="ion-indicator-title">{{ title }}</h1>
<ion-icon
data-testid="ion-indicator-tooltip"
*ngIf="tooltipText"
type="exclamation-rounded"
size="16"
ionTooltip
ionTooltipPosition="bottomLeft"
ionTooltipColorScheme="dark"
ionTooltipTrigger="hover"
[ionTooltipTitle]="tooltipText"
[ionTooltipArrowPointAtCenter]="true"
>
</ion-icon>
</header>
<div class="content with-footer">
<header>
<h4 data-testid="ion-indicator-value">{{ value }}</h4>
<p data-testid="ion-indicator-second-value">{{ secondValue }}</p>
<div
*ngIf="preview"
class="preview-content"
data-testid="ion-indicator-preview"
>
<ion-skeleton variant="rect" [width]="400" [height]="136"></ion-skeleton>
</div>
<div *ngIf="!preview">
<header class="title">
<h1 data-testid="ion-indicator-title">{{ title }}</h1>
<ion-icon
data-testid="ion-indicator-tooltip"
*ngIf="tooltipText"
type="exclamation-rounded"
size="16"
ionTooltip
ionTooltipPosition="bottomLeft"
ionTooltipColorScheme="dark"
ionTooltipTrigger="hover"
[ionTooltipTitle]="tooltipText"
[ionTooltipArrowPointAtCenter]="true"
>
</ion-icon>
</header>
<footer data-testid="ion-indicator-footer" *ngIf="buttonConfig">
<ion-button
[attr.data-testid]="'ion-indicator-button-' + buttonConfig.type"
type="ghost"
size="sm"
rightSideIcon="true"
[label]="buttonConfig.label"
[iconType]="buttonConfig.icon ? buttonConfig.icon : 'right2'"
(ionOnClick)="handleButtonClick(buttonConfig.type)"
></ion-button>
</footer>
<div class="content with-footer">
<div
*ngIf="error"
class="error-container"
data-testid="ion-indicator-error"
>
<ion-icon size="16" type="exclamation-rounded"></ion-icon>
<span>Erro no carregamento</span>
</div>
<div *ngIf="loading && !error">
<ion-spinner
data-testid="ion-indicator-spinner"
[size]="32"
color="primary"
></ion-spinner>
</div>
<header *ngIf="!loading && !error">
<h4 data-testid="ion-indicator-value">{{ value }}</h4>
<p data-testid="ion-indicator-second-value">{{ secondValue }}</p>
</header>
<footer
data-testid="ion-indicator-footer"
*ngIf="buttonConfig && !loading && !error"
>
<ion-button
[attr.data-testid]="'ion-indicator-button-' + buttonConfig.type"
type="ghost"
size="sm"
rightSideIcon="true"
[label]="buttonConfig.label"
[iconType]="buttonConfig.icon ? buttonConfig.icon : 'right2'"
(ionOnClick)="handleButtonClick(buttonConfig.type)"
></ion-button>
</footer>
</div>
</div>
</div>
28 changes: 25 additions & 3 deletions projects/ion/src/lib/indicator/indicator.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
@import '../../styles/index.scss';

@mixin icon-style {
ion-icon {
::ng-deep svg {
fill: $neutral-6;
}
}
}

.ellipsis-in-text {
text-overflow: ellipsis;
white-space: nowrap;
Expand Down Expand Up @@ -32,6 +40,8 @@
border-top-left-radius: 8px;
border-top-right-radius: 8px;

@include icon-style();

h1 {
color: $neutral-7;
font-weight: 600;
Expand Down Expand Up @@ -79,13 +89,25 @@
}
}

.error-container {
color: $neutral-6;
display: flex;
align-items: center;

@include icon-style();

span {
padding-left: 4px;
}
}

&.with-footer {
padding: 12px 0px 0px;
padding: 0px;
flex-direction: column;
justify-content: space-between;
justify-content: center;

header {
padding: 0px 16px 12px;
padding: 12px 16px 12px;
box-sizing: border-box;
}

Expand Down
44 changes: 44 additions & 0 deletions projects/ion/src/lib/indicator/indicator.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
import { IonButtonModule } from '../button/button.module';
import { IonTooltipModule } from '../tooltip/tooltip.module';
import { IonIconModule } from '../icon/icon.module';
import { IonSkeletonModule } from '../skeleton/skeleton.module';
import { IonSpinnerModule } from '../spinner/spinner.module';

@NgModule({
entryComponents: [IonModalComponent, BodyMockComponent],
Expand All @@ -34,6 +36,8 @@ const sut = async (
IonIconModule,
IonTooltipModule,
EntryComponentModule,
IonSkeletonModule,
IonSpinnerModule,
],
declarations: [BodyMockComponent, IonIndicatorComponent, IonModalComponent],
componentProperties: props,
Expand All @@ -49,6 +53,9 @@ const elements = {
buttonEmitter: 'ion-indicator-button-emitter',
buttonRedirect: 'ion-indicator-button-redirect',
buttonModal: 'ion-indicator-button-modal',
preview: 'ion-indicator-preview',
spinner: 'ion-indicator-spinner',
error: 'ion-indicator-error',
};

const getElementByTestId = (key: keyof typeof elements): HTMLElement =>
Expand Down Expand Up @@ -161,4 +168,41 @@ describe('IonIndicatorComponent', () => {
expect(modalTitle).not.toBeInTheDocument();
expect(spy).toHaveBeenCalled();
});

it('Should hide all values when is preview', async () => {
const testTitle = 'Indicator preview';
const valueNumber = 12;
const secondValueNumber = 14;
await sut({
value: valueNumber,
secondValue: secondValueNumber,
title: testTitle,
preview: true,
});

expect(getElementByTestId('title')).not.toBeInTheDocument();
expect(getElementByTestId('value')).not.toBeInTheDocument();
expect(getElementByTestId('secondValue')).not.toBeInTheDocument();
});

it('Should render skeleton when in preview', async () => {
await sut({
preview: true,
});
expect(getElementByTestId('preview')).toBeInTheDocument();
});

it('Should render spinner when is loading', async () => {
await sut({
loading: true,
});
expect(getElementByTestId('spinner')).toBeInTheDocument();
});

it('Should render error msg', async () => {
await sut({
error: true,
});
expect(getElementByTestId('error')).toBeInTheDocument();
});
});
4 changes: 4 additions & 0 deletions projects/ion/src/lib/indicator/indicator.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ export class IonIndicatorComponent {
@Input() value: number | string;
@Input() secondValue: number | string;
@Input() buttonConfig: IonIndicatorButtonConfiguration;
@Input() preview = false;
@Input() loading = false;
@Input() error = false;
@Output() ionClick = new EventEmitter();
@Output() modalEvent = new EventEmitter<IonModalResponse | unknown>();
safeUrl: SafeResourceUrl;

private buttonActions = {
emitter: this.emitButtonClick,
modal: this.openModal,
Expand Down
4 changes: 4 additions & 0 deletions projects/ion/src/lib/indicator/indicator.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { IonButtonModule } from '../button/button.module';
import { IonTooltipModule } from '../tooltip/tooltip.module';
import { IonModalModule } from '../modal/modal.module';
import { IonIconModule } from '../icon/icon.module';
import { IonSkeletonModule } from '../skeleton/skeleton.module';
import { IonSpinnerModule } from '../spinner/spinner.module';

@NgModule({
declarations: [IonIndicatorComponent],
Expand All @@ -14,6 +16,8 @@ import { IonIconModule } from '../icon/icon.module';
IonIconModule,
IonTooltipModule,
IonModalModule,
IonSkeletonModule,
IonSpinnerModule,
],
exports: [IonIndicatorComponent],
})
Expand Down
30 changes: 30 additions & 0 deletions stories/Indicator.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,36 @@ WithTooltip.args = {
secondValue: '5%',
};

export const WithPreview = Template.bind({});
WithPreview.args = {
title: 'preview',
value: 1500,
secondValue: '5%',
tooltipText: 'Texto personalizado via atributo tooltipText',
buttonConfig: buttonEmitterConfig,
preview: true,
};

export const WithLoading = Template.bind({});
WithLoading.args = {
title: 'Tempo de SLA',
value: 1500,
secondValue: '5%',
tooltipText: 'Texto personalizado via atributo tooltipText',
buttonConfig: buttonEmitterConfig,
loading: true,
};

export const WithError = Template.bind({});
WithError.args = {
title: 'Tempo de SLA',
value: 1500,
secondValue: '5%',
tooltipText: 'Texto personalizado via atributo tooltipText',
buttonConfig: buttonEmitterConfig,
error: true,
};

export const WithEmitterButton = Template.bind({});
WithEmitterButton.args = {
title: 'Com botão emitter',
Expand Down

0 comments on commit 8eb06b7

Please sign in to comment.