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 Animation Support for UpWindow Component #2

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"publish": "cd dist/up-window-angular && npm publish",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"test:module": "ng test up-window-angular",
"postbuild": "node scripts/post-build.js"
},
"private": true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
<div class="overlay" [ngClass]="{ active: isOpen() }">
<div class="up-window" [ngClass]="class">
<button class="close-window" (click)="closeWindow()">×</button>
<div class="overlay" [class.active]="isOpen()">
<div class="up-window" [ngClass]="getClass()">
<button class="close-window" (click)="closeWindow()">&times;</button>
<div class="up-window-header">
<div>
<h2 class="up-window-title">{{ title }}</h2>
<p class="up-window-subtitle">{{ subtitle }}</p>
</div>
<h3 class="up-window-title">{{ title }}</h3>
<h4 class="up-window-subtitle">{{ subtitle }}</h4>
</div>

<div class="up-window-body">
<ng-content></ng-content>
</div>

<div class="up-window-footer">
<button class="btn btn-cancel" (click)="onCancel()">Cancel</button>
<button class="btn btn-confirm" (click)="onConfirm()">Confirm</button>
Expand Down
153 changes: 151 additions & 2 deletions projects/up-window-angular/src/lib/up-window-angular.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,51 @@ body {
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin: 1rem;

&.fade {
animation: up-window-fadeIn 0.3s forwards;
}

&.fade-out {
animation: up-window-fadeOut 0.3s forwards;
}

&.slide {
animation: up-window-slideIn 0.3s forwards;
}

&.slide-out {
animation: up-window-slideOut 0.3s forwards;
}

&.slide-up {
animation: up-window-slideUp 0.3s forwards;
}

&.slide-up-out {
animation: up-window-slideUpOut 0.3s forwards;
}

&.slide-down {
animation: up-window-slideDown 0.3s forwards;
}

&.slide-down-out {
animation: up-window-slideDownOut 0.3s forwards;
}

&.scale {
animation: up-window-scaleIn 0.3s forwards;
}

&.scale-out {
animation: up-window-scaleOut 0.3s forwards;
}
}

.up-window-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
}

.up-window-title,
Expand Down Expand Up @@ -109,3 +148,113 @@ body {
background-color: var(--up-window-primary);
color: white;
}

@keyframes up-window-fadeIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

@keyframes up-window-fadeOut {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-20px);
}
}

@keyframes up-window-slideIn {
from {
opacity: 0;
transform: translateX(-100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}

@keyframes up-window-slideOut {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(-100%);
}
}

@keyframes up-window-slideUp {
from {
opacity: 0;
transform: translateY(100%);
}
to {
opacity: 1;
transform: translateY(0);
}
}

@keyframes up-window-slideDown {
from {
opacity: 0;
transform: translateY(-100%);
}
to {
opacity: 1;
transform: translateY(0);
}
}

@keyframes up-window-scaleIn {
from {
opacity: 0;
transform: scale(0.8);
}
to {
opacity: 1;
transform: scale(1);
}
}

@keyframes up-window-scaleOut {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.8);
}
}

@keyframes up-window-slideUpOut {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(100%);
}
}

@keyframes up-window-slideDownOut {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-100%);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,91 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UpWindowAngularComponent } from './up-window-angular.component';
import { By } from '@angular/platform-browser';

describe('UpWindowAngularComponent', () => {
let component: UpWindowAngularComponent;
let fixture: ComponentFixture<UpWindowAngularComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UpWindowAngularComponent],
declarations: [UpWindowAngularComponent],
}).compileComponents();

fixture = TestBed.createComponent(UpWindowAngularComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
it('should create the component', () => {
expect(component).toBeTruthy();
});

it('should render title and subtitle', () => {
component.title = 'Test Title';
component.subtitle = 'Test Subtitle';
fixture.detectChanges();

const titleElement = fixture.debugElement.query(By.css('.up-window-title')).nativeElement;
const subtitleElement = fixture.debugElement.query(By.css('.up-window-subtitle')).nativeElement;

expect(titleElement.textContent).toContain('Test Title');
expect(subtitleElement.textContent).toContain('Test Subtitle');
});

it('should apply the correct animation class when opening and closing the window', () => {
component.animation = 'slide';
component.isOpen.set(true);
fixture.detectChanges();

let windowElement = fixture.debugElement.query(By.css('.up-window'));
expect(windowElement.classes['slide']).toBeTruthy();

component.closeWindow();
fixture.detectChanges();

setTimeout(() => {
windowElement = fixture.debugElement.query(By.css('.up-window'));
expect(windowElement.classes['slide-out']).toBeTruthy();
expect(component.isOpen()).toBeFalse();
}, 300);
});

it('should trigger onConfirm and onCancel when buttons are clicked', () => {
spyOn(component, 'onConfirm').and.callThrough();
spyOn(component, 'onCancel').and.callThrough();

const confirmButton = fixture.debugElement.query(By.css('.btn-confirm')).nativeElement;
const cancelButton = fixture.debugElement.query(By.css('.btn-cancel')).nativeElement;

confirmButton.click();
expect(component.onConfirm).toHaveBeenCalled();

cancelButton.click();
expect(component.onCancel).toHaveBeenCalled();
});

it('should apply custom class from @Input', () => {
component.class = 'custom-class';
fixture.detectChanges();

const windowElement = fixture.debugElement.query(By.css('.up-window'));
expect(windowElement.classes['custom-class']).toBeTruthy();
});

it('should set isOpen to true when openWindow is called', () => {
component.openWindow();
expect(component.isOpen()).toBeTrue();
});

it('should set isOpen to false after closeWindow is called', () => {
component.isOpen.set(true);
fixture.detectChanges();

component.closeWindow();
fixture.detectChanges();

setTimeout(() => {
expect(component.isOpen()).toBeFalse();
}, 300);
});
});
18 changes: 16 additions & 2 deletions projects/up-window-angular/src/lib/up-window-angular.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ export class UpWindowAngularComponent implements OnInit {
@Input() subtitle: string = 'Default Subtitle';
@Input() size: string = 'medium';
@Input() class: string | undefined;

@Input() isOpen: WritableSignal<boolean> = signal(false);
@Input() animation: string = 'fade';
closingAnimation: boolean = false;

ngOnInit(): void {}

Expand All @@ -28,7 +29,20 @@ export class UpWindowAngularComponent implements OnInit {
}

closeWindow() {
this.isOpen.set(false);
this.closingAnimation = true;

setTimeout(() => {
this.isOpen.set(false);
this.closingAnimation = false;
}, 300);
}

getClass() {
return {
...(this.class ? { [this.class]: true } : {}),
[this.animation]: !this.closingAnimation,
[`${this.animation}-out`]: this.closingAnimation,
};
}

onConfirm() {
Expand Down
62 changes: 55 additions & 7 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,64 @@
</button>
</div>
<hr />
<button class="button-modal-example" type="button" (click)="openModalExample()">
Open Modal Example
<button class="button-modal-example" type="button" (click)="openWindowExample('fade')">
Open Fade Example
</button>
<up-window-angular
[isOpen]="isModalOpenExample"
title="Modal Title"
subtitle="This is the subtitle of the modal."
size="medium"
[isOpen]="isWindowOpenFade"
title="Fade Window"
subtitle="This window uses a fade animation."
animation="fade"
>
Modal Example content!
Fade Example content!
</up-window-angular>

<button class="button-modal-example" type="button" (click)="openWindowExample('slide')">
Open Slide Example
</button>
<up-window-angular
[isOpen]="isWindowOpenSlide"
title="Slide Window"
subtitle="This window uses a slide animation."
animation="slide"
>
Slide Example content!
</up-window-angular>

<button class="button-modal-example" type="button" (click)="openWindowExample('slide-up')">
Open Slide Up Example
</button>
<up-window-angular
[isOpen]="isWindowOpenSlideUp"
title="Slide Up Window"
subtitle="This window uses a slide-up animation."
animation="slide-up"
>
Slide Up Example content!
</up-window-angular>

<button class="button-modal-example" type="button" (click)="openWindowExample('slide-down')">
Open Slide Down Example
</button>
<up-window-angular
[isOpen]="isWindowOpenSlideDown"
title="Slide Down Window"
subtitle="This window uses a slide-down animation."
animation="slide-down"
>
Slide Down Example content!
</up-window-angular>

<button class="button-modal-example" type="button" (click)="openWindowExample('scale')">
Open Scale Example
</button>
<up-window-angular
[isOpen]="isWindowOpenScale"
title="Scale Window"
subtitle="This window uses a scale animation."
animation="scale"
>
Scale Example content!
</up-window-angular>
</div>
</main>
Expand Down
Loading