diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts
index ef8ca76b4d..d823596896 100644
--- a/angular-workspace/projects/example-client-app/src/app/app.module.ts
+++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts
@@ -10,14 +10,12 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N
NimbleCardButtonModule, NimbleDialogModule, NimbleRadioGroupModule, NimbleRadioButtonModule } from '@ni/nimble-angular';
import { AppComponent } from './app.component';
import { CustomAppComponent } from './customapp/customapp.component';
-import { LoginComponent } from './login/login.component';
import { HeaderComponent } from './header/header.component';
import { NavDrawerComponent } from './nav-drawer/nav-drawer.component';
@NgModule({
declarations: [
AppComponent,
- LoginComponent,
HeaderComponent,
NavDrawerComponent,
CustomAppComponent
@@ -57,8 +55,7 @@ import { NavDrawerComponent } from './nav-drawer/nav-drawer.component';
NimbleRadioGroupModule,
NimbleRadioButtonModule,
RouterModule.forRoot([
- { path: '', redirectTo: '/login', pathMatch: 'full' },
- { path: 'login', component: LoginComponent },
+ { path: '', redirectTo: '/customapp', pathMatch: 'full' },
{ path: 'customapp', component: CustomAppComponent }
],
{ useHash: true })
diff --git a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
index 47b958b336..f6e0b1f8f2 100644
--- a/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
+++ b/angular-workspace/projects/example-client-app/src/app/customapp/customapp.component.html
@@ -193,13 +193,13 @@
This is a dialog
Default
Tooltip label
Fail
- Tooltip label
+ Tooltip label
Information
- Tooltip label
+ Tooltip label
Fail Icon
- Tooltip label
+ Tooltip label
Information Icon
- Tooltip label
+ Tooltip label
Tree View
diff --git a/angular-workspace/projects/example-client-app/src/app/header/header.component.html b/angular-workspace/projects/example-client-app/src/app/header/header.component.html
index f95eda59fe..92dc954dc3 100644
--- a/angular-workspace/projects/example-client-app/src/app/header/header.component.html
+++ b/angular-workspace/projects/example-client-app/src/app/header/header.component.html
@@ -13,7 +13,6 @@
User settings
Menu
diff --git a/angular-workspace/projects/example-client-app/src/app/header/header.component.ts b/angular-workspace/projects/example-client-app/src/app/header/header.component.ts
index 24c4623c6e..38aa1f55c9 100644
--- a/angular-workspace/projects/example-client-app/src/app/header/header.component.ts
+++ b/angular-workspace/projects/example-client-app/src/app/header/header.component.ts
@@ -36,11 +36,6 @@ export class HeaderComponent {
this.userSettingsDrawer.hide();
}
- public onLogoutSelected(): void {
- this.toggleMenuHidden();
- void this.router.navigate(['/login']);
- }
-
private toggleMenuHidden(): void {
this.hideMenu = !this.hideMenu;
}
diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.html b/angular-workspace/projects/example-client-app/src/app/login/login.component.html
deleted file mode 100644
index cdca4f757a..0000000000
--- a/angular-workspace/projects/example-client-app/src/app/login/login.component.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.scss b/angular-workspace/projects/example-client-app/src/app/login/login.component.scss
deleted file mode 100644
index 6c9ee0a34f..0000000000
--- a/angular-workspace/projects/example-client-app/src/app/login/login.component.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-@import '~@ni/nimble-angular/styles/tokens';
-
-:host {
- background-color: $ni-nimble-application-background-color;
- display: flex;
- flex: auto;
- justify-content: center;
- align-items: center;
- height: 100%;
-}
-
-.login-container {
- display: flex;
- flex-direction: column;
-}
-
-nimble-button {
- margin-bottom: 12px;
- width: fit-content;
-}
-
-nimble-text-field {
- width: 150px;
- margin-bottom: 12px;
-}
diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.ts b/angular-workspace/projects/example-client-app/src/app/login/login.component.ts
deleted file mode 100644
index f006b2cd3b..0000000000
--- a/angular-workspace/projects/example-client-app/src/app/login/login.component.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Component, Inject } from '@angular/core';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
-import { Router } from '@angular/router';
-
-@Component({
- selector: 'example-login',
- templateUrl: './login.component.html',
- styleUrls: ['./login.component.scss']
-})
-export class LoginComponent {
- public loginForm: FormGroup;
- public constructor(private readonly formBuilder: FormBuilder, @Inject(Router) private readonly router: Router) {
- this.loginForm = this.formBuilder.group({
- username: ['someuser', Validators.required],
- password: ['password', Validators.required]
- });
- }
-
- public onSubmit(): void {
- void this.router.navigate(['/customapp']);
- }
-}
diff --git a/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js b/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js
index 174925b48d..67c3eb83dc 100644
--- a/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js
+++ b/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js
@@ -52,6 +52,7 @@ for (const key of Object.keys(icons)) {
const directiveFileContents = `${generatedFilePrefix}
import { Directive } from '@angular/core';
import type { ${className} } from '@ni/nimble-components/dist/esm/icons/${directoryName}';
+import { NimbleIconBaseDirective } from '../../icon-base/nimble-icon-base.directive';
export type { ${className} };
@@ -61,7 +62,7 @@ export type { ${className} };
@Directive({
selector: '${elementName}'
})
-export class ${directiveName} {
+export class ${directiveName} extends NimbleIconBaseDirective {
}
`;
const directiveFileName = `${elementName}.directive`;
diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts
index 8110f8b8f7..c51d339daa 100644
--- a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts
+++ b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts
@@ -1,7 +1,9 @@
-import { Directive } from '@angular/core';
+import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
import type { Breadcrumb } from '@ni/nimble-components/dist/esm/breadcrumb';
+import { BreadcrumbAppearance } from '@ni/nimble-components/dist/esm/breadcrumb/types';
export type { Breadcrumb };
+export { BreadcrumbAppearance };
/**
* Directive to provide Angular integration for the breadcrumb.
@@ -10,4 +12,13 @@ export type { Breadcrumb };
selector: 'nimble-breadcrumb'
})
export class NimbleBreadcrumbDirective {
+ public get appearance(): BreadcrumbAppearance {
+ return this.elementRef.nativeElement.appearance;
+ }
+
+ @Input() public set appearance(value: BreadcrumbAppearance) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'appearance', value);
+ }
+
+ public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef) {}
}
diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts
new file mode 100644
index 0000000000..8ad317e987
--- /dev/null
+++ b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts
@@ -0,0 +1,166 @@
+import { Component, ElementRef, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Breadcrumb, BreadcrumbAppearance, NimbleBreadcrumbDirective } from '../nimble-breadcrumb.directive';
+import { NimbleBreadcrumbModule } from '../nimble-breadcrumb.module';
+
+describe('Nimble breadcrumb', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NimbleBreadcrumbModule]
+ });
+ });
+
+ it('custom element is defined', () => {
+ expect(customElements.get('nimble-breadcrumb')).not.toBeUndefined();
+ });
+
+ describe('with no values in template', () => {
+ @Component({
+ template: `
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective;
+ @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleBreadcrumbDirective;
+ let nativeElement: Breadcrumb;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleBreadcrumbModule]
+ });
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('has expected defaults for appearance', () => {
+ expect(directive.appearance).toBe(BreadcrumbAppearance.default);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default);
+ });
+ });
+
+ describe('with template string values', () => {
+ @Component({
+ template: `
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective;
+ @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleBreadcrumbDirective;
+ let nativeElement: Breadcrumb;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleBreadcrumbModule]
+ });
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('will use template string values for appearance', () => {
+ expect(directive.appearance).toBe(BreadcrumbAppearance.prominent);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent);
+ });
+ });
+
+ describe('with property bound values', () => {
+ @Component({
+ template: `
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective;
+ @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef;
+ public appearance: BreadcrumbAppearance;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleBreadcrumbDirective;
+ let nativeElement: Breadcrumb;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleBreadcrumbModule]
+ });
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with property binding for appearance', () => {
+ expect(directive.appearance).toBe(BreadcrumbAppearance.default);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default);
+
+ fixture.componentInstance.appearance = BreadcrumbAppearance.prominent;
+ fixture.detectChanges();
+
+ expect(directive.appearance).toBe(BreadcrumbAppearance.prominent);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent);
+ });
+ });
+
+ describe('with attribute bound values', () => {
+ @Component({
+ template: `
+
+
+ `
+ })
+ class TestHostComponent {
+ @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective;
+ @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef;
+ public appearance: BreadcrumbAppearance;
+ }
+
+ let fixture: ComponentFixture;
+ let directive: NimbleBreadcrumbDirective;
+ let nativeElement: Breadcrumb;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHostComponent],
+ imports: [NimbleBreadcrumbModule]
+ });
+ fixture = TestBed.createComponent(TestHostComponent);
+ fixture.detectChanges();
+ directive = fixture.componentInstance.directive;
+ nativeElement = fixture.componentInstance.elementRef.nativeElement;
+ });
+
+ it('can be configured with attribute binding for appearance', () => {
+ expect(directive.appearance).toBe(BreadcrumbAppearance.default);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default);
+
+ fixture.componentInstance.appearance = BreadcrumbAppearance.prominent;
+ fixture.detectChanges();
+
+ expect(directive.appearance).toBe(BreadcrumbAppearance.prominent);
+ expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent);
+ });
+ });
+});
diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts
index 6c30121b0c..9af2197ef0 100644
--- a/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts
+++ b/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts
@@ -1,9 +1,11 @@
import { Directive, ElementRef, Input, Renderer2 } from '@angular/core';
import type { Button } from '@ni/nimble-components/dist/esm/button';
-import type { ButtonAppearance, ButtonType } from '@ni/nimble-components/dist/esm/button/types';
+import type { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types';
+import { ButtonType, ButtonAppearanceVariant } from '@ni/nimble-components/dist/esm/button/types';
import { BooleanValueOrAttribute, toBooleanProperty } from '../utilities/template-value-helpers';
-export type { Button, ButtonType };
+export type { Button };
+export { ButtonType, ButtonAppearanceVariant };
/**
* Directive to provide Angular integration for the button.
@@ -20,6 +22,16 @@ export class NimbleButtonDirective {
this.renderer.setProperty(this.elementRef.nativeElement, 'appearance', value);
}
+ public get appearanceVariant(): ButtonAppearanceVariant {
+ return this.elementRef.nativeElement.appearanceVariant;
+ }
+
+ // Renaming because property should have camel casing, but attribute should not
+ // eslint-disable-next-line @angular-eslint/no-input-rename
+ @Input('appearance-variant') public set appearanceVariant(value: ButtonAppearanceVariant) {
+ this.renderer.setProperty(this.elementRef.nativeElement, 'appearanceVariant', value);
+ }
+
public get disabled(): boolean {
return this.elementRef.nativeElement.disabled;
}
@@ -40,7 +52,7 @@ export class NimbleButtonDirective {
return this.elementRef.nativeElement.contentHidden;
}
- // contentHidden property intentionally maps to the content-hidden attribute
+ // Renaming because property should have camel casing, but attribute should not
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('content-hidden') public set contentHidden(value: BooleanValueOrAttribute) {
this.renderer.setProperty(this.elementRef.nativeElement, 'contentHidden', toBooleanProperty(value));
diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts
index b3490b0651..b9fb4bd51e 100644
--- a/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts
+++ b/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts
@@ -2,7 +2,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ButtonAppearance } from '../../../public-api';
import type { BooleanValueOrAttribute } from '../../utilities/template-value-helpers';
-import { Button, NimbleButtonDirective } from '../nimble-button.directive';
+import { Button, NimbleButtonDirective, ButtonAppearanceVariant } from '../nimble-button.directive';
import { NimbleButtonModule } from '../nimble-button.module';
describe('Nimble button', () => {
@@ -54,6 +54,11 @@ describe('Nimble button', () => {
expect(nativeElement.appearance).toBe(ButtonAppearance.outline);
});
+ it('has expected defaults for appearanceVariant', () => {
+ expect(directive.appearanceVariant).toBe(ButtonAppearanceVariant.default);
+ expect(nativeElement.appearanceVariant).toBe(ButtonAppearanceVariant.default);
+ });
+
it('has expected defaults for contentHidden', () => {
expect(directive.contentHidden).toBeFalse();
expect(nativeElement.contentHidden).toBeFalse();
@@ -65,7 +70,8 @@ describe('Nimble button', () => {
template: `
`
})
@@ -99,6 +105,11 @@ describe('Nimble button', () => {
expect(nativeElement.appearance).toBe(ButtonAppearance.ghost);
});
+ it('will use template string values for appearanceVariant', () => {
+ expect(directive.appearanceVariant).toBe(ButtonAppearanceVariant.primary);
+ expect(nativeElement.appearanceVariant).toBe(ButtonAppearanceVariant.primary);
+ });
+
it('will use template string values for contentHidden', () => {
expect(directive.contentHidden).toBeTrue();
expect(nativeElement.contentHidden).toBeTrue();
@@ -111,6 +122,7 @@ describe('Nimble button', () => {
`
@@ -120,6 +132,7 @@ describe('Nimble button', () => {
@ViewChild('button', { read: ElementRef }) public elementRef: ElementRef