Skip to content

Commit

Permalink
Tooltip angular integration (#654)
Browse files Browse the repository at this point in the history
* initial commit

* updates

* updates

* tests and html updates

* updates

* FAST update

* public api updates (#309)

* formatting

* updates

* Change files

* visible fix (#309)

* tooltip angular integration (#309)

* html updates (#309)

* delay updates
  • Loading branch information
aidendk authored Aug 8, 2022
1 parent f0c92dd commit 74efe0c
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,5 @@ NOTE: To update the component status:
| Text Field - Single | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/842889a5-67ba-4350-91c1-55eee48f4fa2/) | | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/docs/text-field--text-field) | :white_check_mark: | :white_check_mark: |
| Toggle Icon Button | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/d022d8af-22f4-4bf2-981c-1dc0c61afece/) | | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/story/toggle-button--icon-button) | :white_check_mark: | :white_check_mark: |
| Toolbar | | [Issue](https://github.com/ni/nimble/issues/411) | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/story/toolbar--toolbar) | :white_check_mark: | :white_check_mark: |
| Tooltip | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/044414d7-1714-40f2-9679-2ce2c8202d1c/) | [Issue](https://github.com/ni/nimble/issues/309) | :o: | :o: | :o: |
| Tooltip | [XD](https://xd.adobe.com/view/33ffad4a-eb2c-4241-b8c5-ebfff1faf6f6-66ac/screen/044414d7-1714-40f2-9679-2ce2c8202d1c/) | [Issue](https://github.com/ni/nimble/issues/309) | [:arrows_counterclockwise: - SB](https://ni.github.io/nimble/storybook/?path=/docs/tooltip--tooltip) | :white_check_mark: | :o: |
| Tree View | | | [:white_check_mark: - SB](https://ni.github.io/nimble/storybook/?path=/docs/tree-view--tree-view) | :white_check_mark: | :white_check_mark: |
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N
NimbleButtonModule, NimbleTreeViewModule, NimbleTreeItemModule, NimbleDrawerModule, NimbleThemeProviderModule,
NimbleTabModule, NimbleTabPanelModule, NimbleTabsModule, NimbleTabsToolbarModule, NimbleMenuModule,
NimbleMenuItemModule, NimbleCheckboxModule, NimbleToggleButtonModule, NimbleBreadcrumbModule, NimbleBreadcrumbItemModule,
NimbleIconAddModule, NimbleSwitchModule, NimbleToolbarModule, NimbleMenuButtonModule, NimbleComboboxModule, NimbleCardButtonModule } from '@ni/nimble-angular';
NimbleIconAddModule, NimbleSwitchModule, NimbleToolbarModule, NimbleMenuButtonModule, NimbleComboboxModule, NimbleTooltipModule, NimbleCardButtonModule } from '@ni/nimble-angular';
import { AppComponent } from './app.component';
import { CustomAppComponent } from './customapp/customapp.component';
import { LoginComponent } from './login/login.component';
Expand Down Expand Up @@ -50,6 +50,7 @@ import { NavDrawerComponent } from './nav-drawer/nav-drawer.component';
NimbleToolbarModule,
NimbleComboboxModule,
NimbleMenuButtonModule,
NimbleTooltipModule,
NimbleCardButtonModule,
RouterModule.forRoot([
{ path: '', redirectTo: '/login', pathMatch: 'full' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@
<nimble-button slot="end" appearance="outline">Last button</nimble-button>
</nimble-toolbar>
</div>
<div class="sub-container">
<div class="container-label">Tooltip</div>
<nimble-button id="anchor1">Default</nimble-button>
<nimble-tooltip anchor="anchor1">Tooltip label</nimble-tooltip>
<nimble-button id="anchor2">Fail</nimble-button>
<nimble-tooltip anchor="anchor2" class="fail">Tooltip label</nimble-tooltip>
<nimble-button id="anchor3">Information</nimble-button>
<nimble-tooltip anchor="anchor3" class="information">Tooltip label</nimble-tooltip>
<nimble-button id="anchor4">Fail Icon </nimble-button>
<nimble-tooltip anchor="anchor4" class="fail icon-visible">Tooltip label</nimble-tooltip>
<nimble-button id="anchor5">Information Icon</nimble-button>
<nimble-tooltip anchor="anchor5" class="information icon-visible">Tooltip label</nimble-tooltip>
</div>
<div class="sub-container">
<div class="container-label">Tree View</div>
<nimble-tree-view>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
import type { Tooltip } from '@ni/nimble-components/dist/esm/tooltip';
import { TooltipStatus } from '@ni/nimble-components/dist/esm/tooltip/types';
import { NumberValueOrAttribute, toNumberProperty } from '../utilities/template-value-helpers';

export type { Tooltip };
export { TooltipStatus };

/**
* Directive to provide Angular integration for the tooltip.
*/
@Directive({
selector: 'nimble-tooltip'
})
export class NimbleTooltipDirective {
public get anchor(): string {
return this.elementRef.nativeElement.anchor;
}

@Input() public set anchor(value: string) {
this.renderer.setProperty(this.elementRef.nativeElement, 'anchor', value);
}

public get delay(): number {
return this.elementRef.nativeElement.delay;
}

@Input() public set delay(value: NumberValueOrAttribute) {
this.renderer.setProperty(this.elementRef.nativeElement, 'delay', toNumberProperty(value));
}

public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef<Tooltip>) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NimbleTooltipDirective } from './nimble-tooltip.directive';

import '@ni/nimble-components/dist/esm/tooltip';

@NgModule({
declarations: [NimbleTooltipDirective],
imports: [CommonModule],
exports: [NimbleTooltipDirective]
})
export class NimbleTooltipModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { Component, ElementRef, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import type { NumberValueOrAttribute } from 'dist/ni/nimble-angular/directives/utilities/template-value-helpers';
import { Tooltip, NimbleTooltipDirective, TooltipStatus } from '../nimble-tooltip.directive';
import { NimbleTooltipModule } from '../nimble-tooltip.module';

describe('Nimble tooltip', () => {
describe('module', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [NimbleTooltipModule]
});
});

it('defines custom element', () => {
expect(customElements.get('nimble-tooltip')).not.toBeUndefined();
});
});

describe('TooltipStatus', () => {
it('can use TooltipStatus values', () => {
// Ensure TooltipStatus is exported correctly so that it can be used
// as more than a type.
expect(TooltipStatus.information).toEqual(TooltipStatus.information);
});
});

describe('with no values in template', () => {
@Component({
template: `
<nimble-tooltip #tooltip></nimble-tooltip>
`
})
class TestHostComponent {
@ViewChild('tooltip', { read: NimbleTooltipDirective }) public directive: NimbleTooltipDirective;
@ViewChild('tooltip', { read: ElementRef }) public elementRef: ElementRef<Tooltip>;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleTooltipDirective;
let nativeElement: Tooltip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleTooltipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('has expected defaults for anchor', () => {
expect(directive.anchor).toBe('');
expect(nativeElement.anchor).toBe('');
});

it('has expected defaults for delay', () => {
expect(directive.delay).toBe(300);
expect(nativeElement.delay).toBe(300);
});
});

describe('with template string values', () => {
@Component({
template: `
<nimble-tooltip #tooltip
anchor="anchor"
delay=300>
</nimble-tooltip>`
})
class TestHostComponent {
@ViewChild('tooltip', { read: NimbleTooltipDirective }) public directive: NimbleTooltipDirective;
@ViewChild('tooltip', { read: ElementRef }) public elementRef: ElementRef<Tooltip>;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleTooltipDirective;
let nativeElement: Tooltip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleTooltipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('will use template string values for anchor', () => {
expect(directive.anchor).toBe('anchor');
expect(nativeElement.anchor).toBe('anchor');
});

it('will use template string values for delay', () => {
expect(directive.delay).toBe(300);
expect(nativeElement.delay).toBe(300);
});
});

describe('with property bound values', () => {
@Component({
template: `
<nimble-tooltip #tooltip
[anchor]="anchor"
[delay]="delay">
</nimble-tooltip>
`
})
class TestHostComponent {
@ViewChild('tooltip', { read: NimbleTooltipDirective }) public directive: NimbleTooltipDirective;
@ViewChild('tooltip', { read: ElementRef }) public elementRef: ElementRef<Tooltip>;
public anchor = 'anchor';
public delay = 300;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleTooltipDirective;
let nativeElement: Tooltip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleTooltipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('can be configured with property binding for anchor', () => {
expect(directive.anchor).toBe('anchor');
expect(nativeElement.anchor).toBe('anchor');

fixture.componentInstance.anchor = 'anchor2';
fixture.detectChanges();

expect(directive.anchor).toBe('anchor2');
expect(nativeElement.anchor).toBe('anchor2');
});
it('can be configured with property binding for delay', () => {
expect(directive.delay).toBe(300);
expect(nativeElement.delay).toBe(300);

fixture.componentInstance.delay = 400;
fixture.detectChanges();

expect(directive.delay).toBe(400);
expect(nativeElement.delay).toBe(400);
});
});

describe('with attribute bound values', () => {
@Component({
template: `
<nimble-tooltip #tooltip
[attr.anchor]="anchor"
[attr.delay]="delay">
</nimble-tooltip>
`
})
class TestHostComponent {
@ViewChild('tooltip', { read: NimbleTooltipDirective }) public directive: NimbleTooltipDirective;
@ViewChild('tooltip', { read: ElementRef }) public elementRef: ElementRef<Tooltip>;
public anchor = 'anchor';
public delay: NumberValueOrAttribute = 300;
}

let fixture: ComponentFixture<TestHostComponent>;
let directive: NimbleTooltipDirective;
let nativeElement: Tooltip;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestHostComponent],
imports: [NimbleTooltipModule]
});
fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
directive = fixture.componentInstance.directive;
nativeElement = fixture.componentInstance.elementRef.nativeElement;
});

it('can be configured with attribute binding for anchor', () => {
expect(directive.anchor).toBe('anchor');
expect(nativeElement.anchor).toBe('anchor');

fixture.componentInstance.anchor = 'anchor2';
fixture.detectChanges();

expect(directive.anchor).toBe('anchor2');
expect(nativeElement.anchor).toBe('anchor2');
});
// Test is disabled because of [FAST bug](https://github.com/microsoft/fast/issues/6257)
xit('can be configured with attribute binding for delay', () => {
expect(directive.delay).toBe(300);
expect(nativeElement.delay).toBe(300);

fixture.componentInstance.delay = 400;
fixture.detectChanges();

expect(directive.delay).toBe(400);
expect(nativeElement.delay).toBe(400);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export * from './directives/tree-item/nimble-tree-item.directive';
export * from './directives/tree-item/nimble-tree-item.module';
export * from './directives/tree-view/nimble-tree-view.directive';
export * from './directives/tree-view/nimble-tree-view.module';
export * from './directives/tooltip/nimble-tooltip.directive';
export * from './directives/tooltip/nimble-tooltip.module';
export * from './testing/async-helpers';

// Export enums that are used by multiple components here to avoid exporting them multiple times.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Tooltip Angular Integration (#309)",
"packageName": "@ni/nimble-angular",
"email": "[email protected]",
"dependentChangeType": "patch"
}

0 comments on commit 74efe0c

Please sign in to comment.