Skip to content

Commit

Permalink
Merge pull request #24 from criar-art/custom-footer
Browse files Browse the repository at this point in the history
Implement Custom Footer for `up-window-angular` Component
  • Loading branch information
lucasferreiralimax authored Oct 17, 2024
2 parents 9bd4a0e + 1b6d2f7 commit c5ea21b
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 20 deletions.
35 changes: 19 additions & 16 deletions projects/up-window-angular/src/lib/up-window-angular.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,25 @@ <h4 id="dialog-description" class="up-window-subtitle">

@if(!hiddenActions) {
<div class="up-window-footer" [ngClass]="'align-' + buttonAlignment">
<button
class="btn btn-cancel"
[ngClass]="getButtonClass(cancelType)"
(click)="onCancel()"
[attr.aria-label]="cancelText"
>
{{ cancelText }}
</button>
<button
class="btn btn-confirm"
[ngClass]="getButtonClass(confirmType)"
(click)="onConfirm()"
[attr.aria-label]="confirmText"
>
{{ confirmText }}
</button>
<ng-content select="[footer]"></ng-content>
@if(!hasFooterContent()) {
<button
class="btn btn-cancel"
[ngClass]="getButtonClass(cancelType)"
(click)="onCancel()"
[attr.aria-label]="cancelText"
>
{{ cancelText }}
</button>
<button
class="btn btn-confirm"
[ngClass]="getButtonClass(confirmType)"
(click)="onConfirm()"
[attr.aria-label]="confirmText"
>
{{ confirmText }}
</button>
}
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ElementRef,
ViewChild,
effect,
ChangeDetectorRef,
} from '@angular/core';

@Component({
Expand Down Expand Up @@ -55,7 +56,7 @@ export class UpWindowAngularComponent implements OnInit, OnDestroy {

@ViewChild('modal') modal!: ElementRef;

constructor() {
constructor(private cdr: ChangeDetectorRef) {
effect(() => {
if (this.isOpen()) {
this.addModalToBody();
Expand Down Expand Up @@ -86,6 +87,7 @@ export class UpWindowAngularComponent implements OnInit, OnDestroy {
this.focusableElements[this.focusableElements.length - 1];
}
}
this.cdr.detectChanges();
}

addModalToBody() {
Expand Down Expand Up @@ -137,6 +139,11 @@ export class UpWindowAngularComponent implements OnInit, OnDestroy {
document.removeEventListener('keydown', this.handleKeydown.bind(this));
}

hasFooterContent(): boolean {
const footerContent = this.modal?.nativeElement.querySelector('[footer]');
return !!footerContent && footerContent.childNodes.length > 0;
}

startOpeningAnimation() {
this.openingAnimation = true;
setTimeout(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UpWindowAngularComponent } from './up-window-angular.component';
import { By } from '@angular/platform-browser';
import { Component, signal, WritableSignal } from '@angular/core';

@Component({
template: `
<up-window-angular
[isOpen]="isWindowOpenFooter"
title="Test Window"
subtitle="Test Subtitle"
>
<div footer>
<p class="custom-footer">Custom Footer Content</p>
<button
class="custom-btn close"
(click)="isWindowOpenFooter.set(false)"
>
Close
</button>
</div>
</up-window-angular>
`,
})
class HostComponentWithCustomFooter {
isWindowOpenFooter: WritableSignal<boolean> = signal(true);
}

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

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

beforeEach(() => {
fixture = TestBed.createComponent(HostComponentWithCustomFooter);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should not render default footer buttons when custom footer is provided', () => {
const confirmButton = fixture.debugElement.query(By.css('.btn-confirm'));
const cancelButton = fixture.debugElement.query(By.css('.btn-cancel'));

expect(confirmButton).toBeNull();
expect(cancelButton).toBeNull();
});

it('should render custom footer content when ng-content is used', () => {
fixture.detectChanges();

const footerTemplate = fixture.debugElement.query(
By.css('.up-window-footer')
);
expect(footerTemplate).toBeTruthy();

const projectedFooter = footerTemplate.query(By.css('.custom-footer'));
console.log('projectedFooter', projectedFooter);

expect(projectedFooter).toBeTruthy();
expect(projectedFooter.nativeElement.textContent).toContain(
'Custom Footer Content'
);
});
});
1 change: 1 addition & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
</div>
<examples-animation />
<examples-mode />
<examples-actions />
</main>
<app-footer></app-footer>
</div>
35 changes: 34 additions & 1 deletion src/app/examples/actions/actions.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,34 @@
<p>actions works!</p>
<div class="content">
<h2 class="content-title">Actions</h2>
<div class="examples">
<button
class="button-modal-example"
type="button"
(click)="openWindowExample('footer')"
>
<span class="material-symbols-outlined"> &#xf3c3; </span> Custom Footer
</button>

<up-window-angular
[isOpen]="isWindowOpenFooter"
title="Custom Footer Example"
subtitle="Choose an action below"
buttonAlignment="start"
>
<p>
This window features a custom footer that provides tailored actions for
your convenience. You can use the buttons below to either close the
window or perform the designated action as per your requirement.
</p>
<div footer>
<button class="custom-btn close" (click)="isWindowOpenFooter.set(false)">
Close
</button>
<button class="custom-btn confirm" (click)="isWindowOpenFooter.set(false)">
Perform Action
</button>
<span>Custom footer example text.</span>
</div>
</up-window-angular>
</div>
</div>
34 changes: 34 additions & 0 deletions src/app/examples/actions/actions.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
$close-color: #dc3545;
$close-hover-color: #c82333;
$confirm-color: #007bff;
$confirm-hover-color: #0056b3;

.custom-btn {
padding: 8px 12px;
margin: 5px;
cursor: pointer;
color: white;
border: none;
border-radius: 4px;
transition: background-color 0.3s;

&.close {
background-color: $close-color;

&:hover {
background-color: $close-hover-color;
}
}

&.confirm {
background-color: $confirm-color;

&:hover {
background-color: $confirm-hover-color;
}
}

&:hover {
opacity: 0.9;
}
}
14 changes: 12 additions & 2 deletions src/app/examples/actions/actions.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Component } from '@angular/core';
import { Component, signal, WritableSignal } from '@angular/core';
import { UpWindowAngularModule } from '../../../../projects/up-window-angular/src/public-api';

@Component({
selector: 'examples-actions',
standalone: true,
imports: [],
imports: [UpWindowAngularModule],
templateUrl: './actions.component.html',
styleUrl: './actions.component.scss'
})
export class ActionsComponent {
isWindowOpenFooter: WritableSignal<boolean> = signal(false);

openWindowExample(type: string) {
this.isWindowOpenFooter.set(false);
switch (type) {
case 'footer':
this.isWindowOpenFooter.set(true);
break;
}
}
}

0 comments on commit c5ea21b

Please sign in to comment.