Skip to content

Commit

Permalink
feat: integrate floating-ui with popover component (#2785)
Browse files Browse the repository at this point in the history
Signed-off-by: Akshat Patel <[email protected]>
  • Loading branch information
Akshat55 authored Apr 5, 2024
1 parent 73a2ed9 commit 26d04ad
Show file tree
Hide file tree
Showing 17 changed files with 944 additions and 343 deletions.
255 changes: 151 additions & 104 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"@angular/common": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0",
"@angular/core": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0",
"@angular/forms": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0",
"@carbon/styles": "^1.48.1",
"@carbon/styles": "^1.54.0",
"rxjs": "^6.0.0 || ^7.0.0",
"zone.js": "^0.11.0"
},
Expand All @@ -85,7 +85,7 @@
"@angular/platform-browser-dynamic": "14.3.0",
"@angular/router": "14.3.0",
"@babel/core": "7.9.6",
"@carbon/styles": "1.48.1",
"@carbon/styles": "1.54.0",
"@carbon/themes": "11.24.0",
"@commitlint/cli": "17.0.3",
"@commitlint/config-conventional": "17.0.3",
Expand Down Expand Up @@ -142,6 +142,7 @@
"@carbon/icon-helpers": "10.37.0",
"@carbon/icons": "11.14.0",
"@carbon/utils-position": "1.1.4",
"@floating-ui/dom": "1.6.3",
"@ibm/telemetry-js": "^1.2.1",
"flatpickr": "4.6.13",
"tslib": "2.3.0"
Expand Down
5 changes: 3 additions & 2 deletions src/ng-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
},
"allowedNonPeerDependencies": [
"@carbon/utils-position",
"flatpickr",
"@carbon/icon-helpers",
"@carbon/icons",
"@carbon/telemetry"
"@carbon/telemetry",
"@floating-ui/dom",
"flatpickr"
]
}
3 changes: 2 additions & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
"license": "Apache-2.0",
"author": "IBM",
"peerDependencies": {
"@carbon/styles": "^1.5.0"
"@carbon/styles": "^1.54.0"
},
"dependencies": {
"@carbon/icon-helpers": "10.37.0",
"@carbon/icons": "11.14.0",
"@carbon/telemetry": "0.1.0",
"@carbon/utils-position": "1.1.4",
"@floating-ui/dom": "1.6.3",
"flatpickr": "4.6.13",
"tslib": "2.3.0"
}
Expand Down
33 changes: 28 additions & 5 deletions src/popover/popover-content.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
import { Component, HostBinding } from "@angular/core";
import {
Component,
HostBinding,
ViewChild,
ElementRef,
AfterViewInit,
ChangeDetectorRef
} from "@angular/core";

/**
* [See demo](../../?path=/story/components-popover--basic)
*/
@Component({
selector: "cds-popover-content, ibm-popover-content",
template: `
<span class="cds--popover-content">
<ng-content></ng-content>
<span class="cds--popover-content" #content>
<div>
<ng-content></ng-content>
</div>
<span *ngIf="autoAlign" class="cds--popover-caret cds--popover--auto-align"></span>
</span>
<span class="cds--popover-caret"></span>
<span *ngIf="!autoAlign" class="cds--popover-caret"></span>
`
})
export class PopoverContent {
export class PopoverContent implements AfterViewInit {
@HostBinding("class.cds--popover") popoverClass = true;
@ViewChild("content") popoverContent: ElementRef;
autoAlign = false;

constructor(private changeDetectorRef: ChangeDetectorRef) {}

ngAfterViewInit(): void {
if (this.popoverContent) {
// Check we are in a popover with autoAlign enabled
this.autoAlign = !!this.popoverContent.nativeElement.closest(".cds--popover--auto-align");
// Run change detection manually to resolve ExpressionHasChanged
this.changeDetectorRef.detectChanges();
}
}
}
28 changes: 23 additions & 5 deletions src/popover/popover.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TestBed, ComponentFixture } from "@angular/core/testing";
import { Component, Input } from "@angular/core";
import { Component, DebugElement, Input } from "@angular/core";
import { By } from "@angular/platform-browser";

import { PopoverContainer, PopoverContent } from "./";
Expand All @@ -12,7 +12,8 @@ import { PopoverContainer, PopoverContent } from "./";
[dropShadow]="dropShadow"
[align]="align"
[caret]="caret"
[highContrast]="highContrast">
[highContrast]="highContrast"
[autoAlign]="autoAlign">
<p>Popover trigger</p>
<cds-popover-content>
<div>
Expand All @@ -28,27 +29,31 @@ class TestPopoverComponent {
@Input() align = "bottom";
@Input() caret = true;
@Input() highContrast = false;
@Input() autoAlign = true;
}

describe("Popover", () => {
let fixture: ComponentFixture<TestPopoverComponent>;
let component: TestPopoverComponent;
let popoverContainerElement: DebugElement;
let popoverDirectiveEl: PopoverContainer;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestPopoverComponent, PopoverContainer, PopoverContent]
});
fixture = TestBed.createComponent(TestPopoverComponent);
component = fixture.componentInstance;
popoverContainerElement = fixture.debugElement.query(By.directive(PopoverContainer));
popoverDirectiveEl = popoverContainerElement.injector.get(PopoverContainer);
fixture.detectChanges();
});


it("should create a popover container & content", () => {
expect(component).toBeTruthy();
const directiveEl = fixture.debugElement.query(By.directive(PopoverContainer));
expect(directiveEl).not.toBeNull();
expect(directiveEl.nativeElement.className.includes("cds--popover-container")).toBeTruthy();
expect(popoverContainerElement).not.toBeNull();
expect(popoverContainerElement.nativeElement.className.includes("cds--popover-container")).toBeTruthy();

const componentEl = fixture.debugElement.query(By.css("cds-popover-content"));
expect(componentEl).not.toBeNull();
Expand Down Expand Up @@ -79,4 +84,17 @@ describe("Popover", () => {
expect(directiveEl.className.includes("cds--popover--drop-shadow")).toBeFalsy();
expect(directiveEl.className.includes("cds--popover--high-contrast")).toBeTruthy();
});

it("should set auto alignment class to wrapper and caret", () => {
expect(popoverContainerElement.nativeElement.classList.contains("cds--popover--auto-align")).toBeTruthy();
expect(popoverContainerElement.nativeElement.querySelector(".cds--popover-caret.cds--popover--auto-align")).toBeDefined();
});

it("should clean up auto placement on close when auto alignment is enabled", () => {
spyOn(popoverDirectiveEl, "cleanUp");
component.isOpen = true;
fixture.detectChanges();
component.isOpen = false;
expect(popoverDirectiveEl.cleanUp).toHaveBeenCalled();
});
});
Loading

0 comments on commit 26d04ad

Please sign in to comment.