Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new "Accordion" component with customizable Inputs #851

Merged
merged 23 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
eb68fbc
feat: collapse
deeved-hiuston-brisa Sep 28, 2023
265617a
test: collpase
deeved-hiuston-brisa Sep 28, 2023
3f9dc34
Merge branch 'main' of github.com:Brisanet/ion into 849-collapse
deeved-hiuston-brisa Sep 28, 2023
abf6963
docs: collpase storybook
deeved-hiuston-brisa Sep 28, 2023
2d12dc9
docs: collpase custom color
deeved-hiuston-brisa Sep 28, 2023
13eb3eb
docs: change exemple custom templete header
deeved-hiuston-brisa Sep 28, 2023
dbe3b56
Merge branch 'main' into 849-collapse
alysson-mascarenhas-brisa Sep 29, 2023
9352cf0
docs: remove data
deeved-hiuston-brisa Sep 29, 2023
07cde04
Merge branch 'main' into 849-collapse
iurynogueira Sep 29, 2023
96296f2
refactor: collapse
deeved-hiuston-brisa Oct 2, 2023
b5b9b9a
Merge branch '849-collapse' of github.com:Brisanet/ion into 849-collapse
deeved-hiuston-brisa Oct 2, 2023
022ed7d
refactor: changing the component name to accordion
deeved-hiuston-brisa Oct 2, 2023
a59a7c6
Merge branch 'main' into 849-collapse
alysson-mascarenhas-brisa Oct 3, 2023
cfee6fb
Update projects/ion/src/lib/accordion/accordion.component.ts
deeved-hiuston-brisa Oct 3, 2023
52c42d8
Update projects/ion/src/lib/accordion/accordion.component.spec.ts
deeved-hiuston-brisa Oct 3, 2023
df37708
style: add cursor point
deeved-hiuston-brisa Oct 3, 2023
898bf00
Merge branch 'main' into 849-collapse
alysson-mascarenhas-brisa Oct 3, 2023
f1323f5
refactor: adding error handling when the name and templateHeader prop…
deeved-hiuston-brisa Oct 3, 2023
4e4436a
Merge branch '849-collapse' of github.com:Brisanet/ion into 849-collapse
deeved-hiuston-brisa Oct 3, 2023
10dccf0
fix: changing order of icons
deeved-hiuston-brisa Oct 3, 2023
ae31555
Merge branch 'main' into 849-collapse
iurynogueira Oct 3, 2023
39779ba
Merge branch 'main' into 849-collapse
iurynogueira Oct 4, 2023
3455757
Merge branch 'main' into 849-collapse
iurynogueira Oct 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions projects/ion/src/lib/accordion/accordion.component.html
deeved-hiuston-brisa marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<section
data-testid="ion-accordion"
[class.open]="show"
[class.close]="!show"
tabindex="0"
>
<header (click)="toggle()">
<div>
<div
*ngIf="!templateHeader; else headerCustom"
data-testid="ion-accordion__header-name"
>
{{ name }}
</div>
<ng-template
#headerCustom
[ngTemplateOutlet]="templateHeader"
></ng-template>
</div>
<ion-icon *ngIf="!show" type="semi-up" [size]="iconSize"></ion-icon>
<ion-icon *ngIf="show" type="semi-down" [size]="iconSize"></ion-icon>
deeved-hiuston-brisa marked this conversation as resolved.
Show resolved Hide resolved
</header>
<main *ngIf="show" data-testid="ion-accordion__main">
<ng-content></ng-content>
</main>
</section>
66 changes: 66 additions & 0 deletions projects/ion/src/lib/accordion/accordion.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@import '../../styles/index.scss';

@mixin accordion-style($bgColor, $color) {
header {
color: $color;
border-bottom: 1px solid $color;
background-color: $bgColor;

ion-icon {
::ng-deep svg {
fill: $color;
}
}
}
}

section {
@include accordion-style($neutral-1, $neutral-7);
header,
main {
padding: 16px 20px;
}

header {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 64px;
box-sizing: border-box;
cursor: pointer;

div {
div {
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
}
}

main {
background-color: $neutral-1;
}

&:hover {
@include accordion-style($neutral-2, $primary-3);
}

&:active {
@include accordion-style($primary-2, $primary-4);
}

&:focus-visible {
outline: 2px solid $primary-4;
}

&.open {
@include accordion-style($primary-1, $primary-4);
}

&.close {
header {
border-bottom: 1px solid $neutral-4;
}
}
}
112 changes: 112 additions & 0 deletions projects/ion/src/lib/accordion/accordion.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { screen, fireEvent } from '@testing-library/angular';

import { Component, NgModule } from '@angular/core';
import { IonAccordionModule } from './accordion.module';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { IonIconModule } from '../icon/icon.module';

@Component({
template: `<ion-accordion [name]="name">
<p data-testID="ion-accordion__main-paragraph">Context Main</p>
</ion-accordion>`,
})
class AccordionTestComponent {
name = '';
}

@Component({
template: `<ion-accordion [templateHeader]="customHeader">
<p data-testID="ion-accordion__main-paragraph">Context Main</p>
</ion-accordion>
<ng-template #customHeader>
<div data-testId="ion-accordion__header-custom">
Custom template header
<ion-icon type="zoom-in"></ion-icon></div
></ng-template>`,
})
class AccordionWithTemplateHeaderTestComponent {}

@NgModule({
declarations: [
AccordionTestComponent,
AccordionWithTemplateHeaderTestComponent,
],
imports: [IonAccordionModule, IonIconModule],
})
class AccordionTestModule {}

describe('IonAccordion', () => {
let accordionTestComponent!: AccordionTestComponent;
let fixture!: ComponentFixture<AccordionTestComponent>;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [AccordionTestModule],
}).compileComponents();
fixture = TestBed.createComponent(AccordionTestComponent);
accordionTestComponent = fixture.componentInstance;
fixture.detectChanges();
});

afterEach(async () => {
fixture.destroy();
});

it('should render ion-accordion', async () => {
expect(screen.getByTestId('ion-accordion')).toBeTruthy();
});

it('should render ion-accordion with name Brisanet', async () => {
const accordionName = 'Brisanet';
accordionTestComponent.name = accordionName;
fixture.detectChanges();
expect(screen.getByTestId('ion-accordion__header-name')).toHaveTextContent(
accordionName
);
});

it('should render main when clicking on header', async () => {
const header = screen.getByTestId('ion-accordion__header-name');
fireEvent.click(header);
fixture.detectChanges();
expect(screen.getByTestId('ion-accordion__main')).toBeTruthy();
expect(
screen.getByTestId('ion-accordion__main-paragraph')
).toHaveTextContent('Context Main');
});

it('should not render main when clicking on header twice', async () => {
const header = screen.getByTestId('ion-accordion__header-name');
fireEvent.click(header);
fireEvent.click(header);
fixture.detectChanges();
expect(screen.queryByTestId('ion-accordion__main')).not.toBeTruthy();
});
});

describe('IonAccordion - template header', () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let accordionWithTemplateHeaderTestComponent!: AccordionWithTemplateHeaderTestComponent;
let fixture!: ComponentFixture<AccordionWithTemplateHeaderTestComponent>;
beforeEach(async () => {
TestBed.configureTestingModule({
imports: [CommonModule, AccordionTestModule],
}).compileComponents();
fixture = TestBed.createComponent(AccordionWithTemplateHeaderTestComponent);
accordionWithTemplateHeaderTestComponent = fixture.componentInstance;
fixture.detectChanges();
});

afterEach(async () => {
fixture.destroy();
});

it('should render template header', async () => {
const headerCustom = await screen.getByTestId(
'ion-accordion__header-custom'
);
expect(headerCustom).toBeTruthy();
expect(headerCustom).toHaveTextContent('Custom template header');
expect(document.getElementById('ion-icon-zoom-in')).toBeTruthy();
});
});
19 changes: 19 additions & 0 deletions projects/ion/src/lib/accordion/accordion.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component, Input } from '@angular/core';
import { TemplateHeader } from '../core/types/accordion';

@Component({
selector: 'ion-accordion',
templateUrl: './accordion.component.html',
styleUrls: ['./accordion.component.scss'],
})
export class IonAccordionComponent {
@Input() name?: string;
@Input() templateHeader?: TemplateHeader;
@Input() show? = false;

iconSize = 24;

toggle(): void {
this.show = !this.show;
}
}
11 changes: 11 additions & 0 deletions projects/ion/src/lib/accordion/accordion.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonAccordionComponent } from './accordion.component';
import { IonIconModule } from '../icon/icon.module';

@NgModule({
declarations: [IonAccordionComponent],
imports: [CommonModule, IonIconModule],
exports: [IonAccordionComponent],
})
export class IonAccordionModule {}
9 changes: 9 additions & 0 deletions projects/ion/src/lib/core/types/accordion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TemplateRef } from '@angular/core';

export type TemplateHeader = TemplateRef<HTMLElement> | null;

export interface IonAccordionProps {
name?: string;
templateHeader?: TemplateHeader;
show?: boolean;
}
1 change: 1 addition & 0 deletions projects/ion/src/lib/core/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * from './tab-group';
export * from './table';
export * from './tag';
export * from './tooltip';
export * from './accordion';
1 change: 1 addition & 0 deletions projects/ion/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ export * from './lib/typography/';
export { default as debounce } from './lib/utils/debounce';
export { default as BnTable } from './core/bn-table/bn-table';
export * from './lib/table/utilsTable';
export * from './lib/accordion/accordion.module';
62 changes: 62 additions & 0 deletions stories/Accordion.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { CommonModule } from '@angular/common';
import { Meta, Story } from '@storybook/angular/types-6-0';
import { IonIconModule } from '../projects/ion/src/lib/icon/icon.module';
import { IonTooltipModule } from '../projects/ion/src/lib/tooltip/tooltip.module';
import { IonAccordionComponent } from '../projects/ion/src/lib/accordion/accordion.component';
import { IonAccordionModule } from '../projects/ion/src/lib/accordion/accordion.module';

export default {
title: 'Ion/Data Display/Accordion',
component: IonAccordionComponent,
} as Meta;

const TemplateAccordionMainContent: Story = (args) => ({
props: args,
template: `<ion-accordion [name]="name"><p style="margin:0">The main code should go here</p></ion-accordion>`,
moduleMetadata: {
imports: [CommonModule, IonIconModule, IonAccordionModule],
},
});

export const accordion = TemplateAccordionMainContent.bind({});
accordion.name = 'Accordion name example';

const TemplateAccordionCustomHeader: Story = (args) => ({
props: args,
template: `
<ion-accordion
[templateHeader]="customHeader"
color="burlywood"
>
<p>Uma terminação de linha óptica, também chamada de terminal de linha óptica, é um dispositivo que serve como ponto final do provedor de serviços de uma rede óptica passiva. </p>
</ion-accordion>

<ng-template #customHeader>
<div style="display:flex; align-items:center; gap: 8px;">
<ion-icon type="olt"></ion-icon><b>OLT</b>
<ion-icon
type="information"
[size]=14
color="#6868ff"
ionTooltip
ionTooltipTitle="Terminação de Linha Óptica"
ionTooltipPosition="topCenter"
[ionTooltipArrowPointAtCenter]="true"
ionTooltipColorScheme="dark"
ionTooltipTrigger="hover"
ionTooltipShowDelay="0"
></ion-icon>
</div>
</ng-template>
`,
moduleMetadata: {
imports: [
CommonModule,
IonIconModule,
IonAccordionModule,
IonTooltipModule,
],
},
});

export const AccordionCustomHeader = TemplateAccordionCustomHeader.bind({});
Loading