Skip to content

Commit

Permalink
Added PopperJs for Modus Tooltips (#1859)
Browse files Browse the repository at this point in the history
  • Loading branch information
msankaran0712 authored Nov 8, 2023
1 parent ca511b9 commit 3bfe125
Show file tree
Hide file tree
Showing 15 changed files with 472 additions and 204 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,14 @@ export declare interface ModusCheckbox extends Components.ModusCheckbox {


@ProxyCmp({
inputs: ['ariaLabel', 'chipStyle', 'disabled', 'hasError', 'imageUrl', 'showCheckmark', 'showClose', 'size', 'value']
inputs: ['ariaLabel', 'chipStyle', 'disabled', 'hasError', 'imageUrl', 'maxWidth', 'showCheckmark', 'showClose', 'size', 'value']
})
@Component({
selector: 'modus-chip',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['ariaLabel', 'chipStyle', 'disabled', 'hasError', 'imageUrl', 'showCheckmark', 'showClose', 'size', 'value'],
inputs: ['ariaLabel', 'chipStyle', 'disabled', 'hasError', 'imageUrl', 'maxWidth', 'showCheckmark', 'showClose', 'size', 'value'],
})
export class ModusChip {
protected el: HTMLElement;
Expand Down
10 changes: 10 additions & 0 deletions stencil-workspace/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions stencil-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"start-storybook": "npm run build && cd storybook && npm run storybook"
},
"dependencies": {
"@popperjs/core": "^2.11.8",

Check warning on line 42 in stencil-workspace/package.json

View workflow job for this annotation

GitHub Actions / spellcheck

Unknown word (popperjs)
"@stencil/core": "^3.3.0",
"@tanstack/table-core": "^8.8.5"
},
Expand Down
12 changes: 10 additions & 2 deletions stencil-workspace/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ export namespace Components {
* (optional) The image's url.
*/
"imageUrl": string;
/**
* (optional) Maximum width for the Chip's text and shows ellipsis when truncated
*/
"maxWidth": string;
/**
* (optional) Whether to show the checkmark.
*/
Expand Down Expand Up @@ -1346,7 +1350,7 @@ export namespace Components {
/**
* (optional) The tooltip's position relative to its content.
*/
"position": 'bottom' | 'left' | 'right' | 'top';
"position": ToolTipPlacement;
/**
* The tooltip's text.
*/
Expand Down Expand Up @@ -2207,6 +2211,10 @@ declare namespace LocalJSX {
* (optional) The image's url.
*/
"imageUrl"?: string;
/**
* (optional) Maximum width for the Chip's text and shows ellipsis when truncated
*/
"maxWidth"?: string;
/**
* An event that fires on chip click.
*/
Expand Down Expand Up @@ -3425,7 +3433,7 @@ declare namespace LocalJSX {
/**
* (optional) The tooltip's position relative to its content.
*/
"position"?: 'bottom' | 'left' | 'right' | 'top';
"position"?: ToolTipPlacement;
/**
* The tooltip's text.
*/
Expand Down
78 changes: 18 additions & 60 deletions stencil-workspace/src/components/modus-navbar/modus-navbar.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,17 @@ describe('modus-navbar', () => {
navbar.setProperty('searchTooltip', { text: 'Search' });
await page.waitForChanges();

const tooltip = await page.find('modus-navbar >>> :first-child');
const tooltipText = await tooltip.find('modus-tooltip >>> .text');
expect(await tooltipText.isVisible()).toBe(false);
const tooltip = await searchIcon.find('modus-tooltip >>> .tooltip');
expect(tooltip.getAttribute('data-show')).toBeNull();

await searchIcon.find('modus-tooltip >>> .modus-tooltip').then((e) => e.hover());
await searchIcon.hover();
await page.waitForChanges();

expect(await tooltipText.isVisible()).toBe(true);
expect(tooltipText.innerText).toBe('Search');
await new Promise((r) => setTimeout(r, 500));
expect(tooltip.getAttribute('data-show')).not.toBeNull();

const tooltipText = await page.$eval('modus-navbar >>> modus-tooltip >>> .tooltip', (tooltip) => tooltip.textContent);
expect(tooltipText).toBe('Search');
});

it('should show searchoverlay on search button click', async () => {
Expand Down Expand Up @@ -301,7 +303,7 @@ describe('modus-navbar', () => {
expect(await productLogo.isVisible()).toBe(true);
});

it('should show tooltip on hover of profile menu', async () => {
it('should show tooltip on hover of profile menu and hide it when menu is open', async () => {
const page = await newE2EPage();
await page.setContent('<modus-navbar></modus-navbar>');

Expand All @@ -312,66 +314,22 @@ describe('modus-navbar', () => {
await page.waitForChanges();

const profileMenuButton = await page.find('modus-navbar >>> .profile-menu');
const tooltipText = await profileMenuButton.find('modus-tooltip >>> .text');

expect(await tooltipText.isVisible()).toBe(false);

await profileMenuButton.find('modus-tooltip >>> .modus-tooltip').then((e) => e.hover());

await page.waitForChanges();

expect(await tooltipText.isVisible()).toBe(true);
expect(tooltipText.innerText).toBe('Modus User');
});

it('should hide tooltip on hovering over of profile menu', async () => {
const page = await newE2EPage();
await page.setContent('<modus-navbar profile-menu-tooltip-text="Modus User"></modus-navbar>');

await page.waitForChanges();

const navbar = await page.find('modus-navbar');
navbar.setProperty('profileMenuOptions', { tooltip: { text: 'Modus User' } });
await page.waitForChanges();

const profileMenuButton = await page.find('modus-navbar >>> .profile-menu');
const tooltipText = await profileMenuButton.find('modus-tooltip >>> .text');

await profileMenuButton.find('modus-tooltip >>> .modus-tooltip').then((e) => e.hover());

await page.waitForChanges();

page.mouse.move(0, 0);

await page.waitForChanges();
expect(await tooltipText.isVisible()).toBe(false);
});

it('should hide tooltip while profile menu open', async () => {
const page = await newE2EPage();
await page.setContent('<modus-navbar profile-menu-tooltip-text="Modus User"></modus-navbar>');

await page.waitForChanges();
const tooltip = await profileMenuButton.find('modus-tooltip >>> .tooltip');
expect(tooltip.getAttribute('data-show')).toBeNull();

const navbar = await page.find('modus-navbar');
navbar.setProperty('profileMenuOptions', { tooltip: { text: 'Modus User' } });
await profileMenuButton.hover();
await page.waitForChanges();

const profileMenuButton = await page.find('modus-navbar >>> .profile-menu');
const tooltipText = await profileMenuButton.find('modus-tooltip >>> .text');
await new Promise((r) => setTimeout(r, 500));
expect(tooltip.getAttribute('data-show')).not.toBeNull();

await profileMenuButton.find('modus-tooltip >>> .modus-tooltip').then((e) => e.hover());

await page.waitForChanges();
const tooltipText = await page.$eval('modus-navbar >>> modus-tooltip >>> .tooltip', (tooltip) => tooltip.textContent);
expect(tooltipText).toBe('Modus User');

await profileMenuButton.click();

await page.waitForChanges();

const profileMenu = await page.find('modus-navbar >>> modus-navbar-profile-menu');

expect(await profileMenu.isVisible()).toBe(true);
expect(await tooltipText.isVisible()).toBe(false);
await new Promise((r) => setTimeout(r, 500));
expect(tooltip.getAttribute('data-show')).toBeNull();
});

it('should render primary logo in all screen when secondary logo not provided', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,31 +93,31 @@ export class ModusSideNavigationItem {
const classes = `side-nav-item${this.expanded ? ' expanded' : ''}${this.selected ? ' selected' : ''}${
this.disabled ? ' disabled' : ''
}`;
const menuIconTooltip = this.expanded || this.disabled ? null : this.label;
const menuIconTooltip = this.label;

return (
<li
role="treeitem"
ref={(el) => (this._itemRef = el)}
tabIndex={this.disabled ? -1 : 0}
class={classes}
onClick={() => this.handleClick()}
onKeyDown={(e) => this.handleKeyDown(e)}
aria-disabled={this.disabled ? 'true' : null}
aria-label={this.label}
aria-current={this.selected ? 'true' : null}
onFocus={() => this.sideNavItemFocus.emit({ id: this.element.id })}>
<div class="menu-icon" onClick={() => this.sideNavItemFocus.emit({ id: this.element.id })}>
<modus-tooltip text={menuIconTooltip} position="right">
<modus-tooltip text={menuIconTooltip} disabled={this.disabled} position="right">
<li
role="treeitem"
ref={(el) => (this._itemRef = el)}
tabIndex={this.disabled ? -1 : 0}
class={classes}
onClick={() => this.handleClick()}
onKeyDown={(e) => this.handleKeyDown(e)}
aria-disabled={this.disabled ? 'true' : null}
aria-label={this.label}
aria-current={this.selected ? 'true' : null}
onFocus={() => this.sideNavItemFocus.emit({ id: this.element.id })}>
<div class="menu-icon" onClick={() => this.sideNavItemFocus.emit({ id: this.element.id })}>
<slot name="menu-icon"></slot>
{this.menuIcon && <IconMap icon={this.menuIcon} aria-label={this.label} size="24"></IconMap>}
</modus-tooltip>
</div>
</div>

{this.expanded && <div class="menu-text">{this.label}</div>}
{this.expanded && <div class="menu-text">{this.label}</div>}

<div class="level-icon">{this.showExpandIcon && <IconMap icon="chevron-right-thick" />}</div>
</li>
<div class="level-icon">{this.showExpandIcon && <IconMap icon="chevron-right-thick" />}</div>
</li>
</modus-tooltip>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ describe('modus-side-navigation-item', () => {
expect(page.root).toEqualHtml(`
<modus-side-navigation-item label="Test">
<mock:shadow-root>
<modus-tooltip position="right" text="Test">
<li class="side-nav-item" role="treeitem" aria-label="Test" tabindex="0">
<div class="menu-icon">
<modus-tooltip position="right" text="Test">
<slot name="menu-icon"></slot>
</modus-tooltip>
</div>
<div class="level-icon">
</div>
</li>
</modus-tooltip>
</mock:shadow-root>
</modus-side-navigation-item>
`);
Expand Down
54 changes: 40 additions & 14 deletions stencil-workspace/src/components/modus-tooltip/modus-tooltip.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,35 @@ describe('modus-tooltip', () => {
it('renders changes to text', async () => {
const page = await newE2EPage();

await page.setContent('<modus-tooltip text="Hello"></modus-tooltip>');
await page.setContent('<modus-tooltip></modus-tooltip>');

let text = await page.find('modus-tooltip >>> .text');
expect(text.textContent).toEqual('Hello');
let text = await page.find('modus-tooltip >>> .tooltip');
expect(text).toHaveClass('hide');

const tooltip = await page.find('modus-tooltip');
tooltip.setProperty('text', 'Something else');
tooltip.setProperty('text', 'Something');
await page.waitForChanges();
text = await page.find('modus-tooltip >>> .text');
expect(text.textContent).toEqual('Something else');

text = await page.find('modus-tooltip >>> .tooltip');
expect(text.textContent).toEqual('Something');
});

it('renders changes to the position', async () => {
const page = await newE2EPage();

await page.setContent('<modus-tooltip></modus-tooltip>');
await page.setContent(`
<modus-tooltip text="Tooltip text...">
<modus-button>Button</modus-button>
</modus-tooltip>
`);
const component = await page.find('modus-tooltip');
const element = await page.find('modus-tooltip >>> .modus-tooltip');
expect(element).toHaveClass('top');
let element = await page.find('modus-tooltip >>> .tooltip');
expect(element.getAttribute('data-popper-placement')).toEqual('top');

component.setProperty('position', 'bottom');
await page.waitForChanges();
expect(element).toHaveClass('bottom');
element = await page.find('modus-tooltip >>> .tooltip');
expect(element.getAttribute('data-popper-placement')).toEqual('bottom');
});

it('tooltip should show or hide if disabled prop set', async () => {
Expand All @@ -44,12 +50,32 @@ describe('modus-tooltip', () => {

tooltip.setProperty('disabled', false);
await page.waitForChanges();
let text = await page.find('modus-tooltip >>> .text');
expect(text.textContent).toEqual('Hello');
let text = await page.find('modus-tooltip >>> .tooltip');
expect(text).not.toHaveClass('hide');

tooltip.setProperty('disabled', true);
await page.waitForChanges();
text = await page.find('modus-tooltip >>> .text');
expect(text).toEqual(null);
text = await page.find('modus-tooltip >>> .tooltip');
expect(text).toHaveClass('hide');
});

it('should display tooltip on hover', async () => {
const page = await newE2EPage();

await page.setContent(`
<modus-tooltip text="Tooltip text">
<modus-button>Button</modus-button>
</modus-tooltip>
`);
await page.hover('modus-button'); // Hover over the element that triggers the tooltip
await new Promise((r) => setTimeout(r, 500));

const tooltip = await page.find('modus-tooltip >>> .tooltip');
expect(tooltip.getAttribute('data-show')).not.toBeNull();

const button = await page.find('modus-button >>> button');
await button.click();
await new Promise((r) => setTimeout(r, 500));
expect(tooltip.getAttribute('data-show')).toBeNull();
});
});
Loading

0 comments on commit 3bfe125

Please sign in to comment.