Skip to content

Commit 1a0d1f5

Browse files
authored
feat(design): convert menu component to standalone (#3130)
1 parent fa6f4db commit 1a0d1f5

15 files changed

+118
-55
lines changed

libs/design/menu/README.md

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ Menus only appear when a user interacts with a menu activator button. They shoul
77
## Basic Menu
88
<design-land-example-viewer-container example="basic-menu"></design-land-example-viewer-container>
99

10+
## Usage
11+
12+
To use menu, import `DaffMenuModule` into your custom module:
13+
14+
```ts
15+
import { NgModule } from '@angular/core';
16+
17+
import { DaffMenuModule } from '@daffodil/design/menu';
18+
19+
@NgModule({
20+
declarations: [
21+
CustomComponent,
22+
],
23+
exports: [
24+
CustomComponent,
25+
],
26+
imports: [
27+
DaffMenuModule,
28+
],
29+
})
30+
export class CustomComponentModule { }
31+
```
32+
1033
## Supported Content Types
1134

1235
### Menu Item

libs/design/menu/examples/src/basic-menu/basic-menu.component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import { MenuContentComponent } from './menu-content/menu-content.component';
1414
templateUrl: './basic-menu.component.html',
1515
changeDetection: ChangeDetectionStrategy.OnPush,
1616
standalone: true,
17-
imports: [DAFF_BUTTON_COMPONENTS, DaffMenuModule],
17+
imports: [
18+
DAFF_BUTTON_COMPONENTS,
19+
DaffMenuModule,
20+
],
1821
})
1922
export class BasicMenuComponent {
2023
public menu = MenuContentComponent;
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<daff-menu>
22
<a href="#" daff-menu-item>
3-
<fa-icon [icon]="faUser" [fixedWidth]="true"></fa-icon> My Account
3+
<fa-icon [icon]="faUser" [fixedWidth]="true" daffPrefix></fa-icon> My Account
44
</a>
55
<a href="#" daff-menu-item>
6-
<fa-icon [icon]="faInfo" [fixedWidth]="true"></fa-icon> Help
6+
<fa-icon [icon]="faInfo" [fixedWidth]="true" daffPrefix></fa-icon> Help
77
</a>
88
<button daff-menu-item>
9-
<fa-icon [icon]="faEnvelope" [fixedWidth]="true"></fa-icon> Contact Us
9+
<fa-icon [icon]="faEnvelope" [fixedWidth]="true" daffPrefix></fa-icon> Contact Us
1010
</button>
1111
</daff-menu>

libs/design/menu/examples/src/basic-menu/menu-content/menu-content.component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import { DaffMenuModule } from '@daffodil/design/menu';
1717
templateUrl: './menu-content.component.html',
1818
changeDetection: ChangeDetectionStrategy.OnPush,
1919
standalone: true,
20-
imports: [DaffMenuModule, FaIconComponent],
20+
imports: [
21+
DaffMenuModule,
22+
FaIconComponent,
23+
],
2124
})
2225
export class MenuContentComponent {
2326
faUser = faUser;

libs/design/menu/src/menu-activator/menu-activator.component.spec.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,21 @@ import { By } from '@angular/platform-browser';
1010
import { BehaviorSubject } from 'rxjs';
1111

1212
import { DaffMenuActivatorDirective } from './menu-activator.component';
13-
import { DaffMenuModule } from '../menu.module';
13+
import { DaffMenuComponent } from '../menu/menu.component';
1414
import { DaffMenuService } from '../services/menu.service';
1515
import { provideTestMenuService } from '../testing/dummy-service';
1616

17-
@Component({ template: `
18-
<button daffMenuActivator="menu"></button>
19-
<daff-menu #menu></daff-menu>
20-
` })
17+
@Component({
18+
template: `
19+
<button daffMenuActivator="menu"></button>
20+
<daff-menu #menu></daff-menu>
21+
`,
22+
standalone: true,
23+
imports: [
24+
DaffMenuComponent,
25+
DaffMenuActivatorDirective,
26+
],
27+
})
2128
class WrapperComponent {}
2229

2330
describe('@daffodil/design/menu | DaffMenuActivatorDirective', () => {
@@ -28,9 +35,6 @@ describe('@daffodil/design/menu | DaffMenuActivatorDirective', () => {
2835
beforeEach(() => {
2936
TestBed.configureTestingModule({
3037
imports: [
31-
DaffMenuModule,
32-
],
33-
declarations: [
3438
WrapperComponent,
3539
],
3640
providers: [

libs/design/menu/src/menu-activator/menu-activator.component.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { DaffMenuService } from '../services/menu.service';
1818

1919
@Directive({
2020
selector: '[daffMenuActivator]',
21+
standalone: true,
2122
})
2223
export class DaffMenuActivatorDirective implements OnDestroy {
2324

libs/design/menu/src/menu-item/menu-item.component.scss

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
:host {
44
@include interactions.clickable();
5-
display: block;
5+
display: flex;
6+
align-items: center;
7+
gap: 8px;
68
border: none;
79
border-radius: 4px;
810
margin: 0;
@@ -13,8 +15,6 @@
1315

1416
.daff-menu-item {
1517
&__content {
16-
display: flex;
17-
gap: 8px;
1818
font-size: 1rem;
1919
line-height: 1.25rem;
2020
text-align: left;

libs/design/menu/src/menu-item/menu-item.component.spec.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import { DaffMenuItemComponent } from './menu-item.component';
1616
<a href="/test" daff-menu-item>Test 1</a>
1717
<button daff-menu-item>Test 2</button>
1818
`,
19+
standalone: true,
20+
imports: [
21+
DaffMenuItemComponent,
22+
],
1923
})
2024

2125
class WrapperComponent {}
@@ -30,8 +34,7 @@ describe('@daffodil/design/menu | DaffMenuItemComponent', () => {
3034

3135
beforeEach(waitForAsync(() => {
3236
TestBed.configureTestingModule({
33-
declarations: [
34-
DaffMenuItemComponent,
37+
imports: [
3538
WrapperComponent,
3639
],
3740
})

libs/design/menu/src/menu-item/menu-item.component.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
import { NgIf } from '@angular/common';
12
import {
23
Component,
34
ChangeDetectionStrategy,
45
HostBinding,
56
ContentChild,
67
} from '@angular/core';
78

8-
import { DaffPrefixDirective } from '@daffodil/design';
9+
import {
10+
DaffPrefixDirective,
11+
DaffPrefixSuffixModule,
12+
} from '@daffodil/design';
913

1014
@Component({
1115
selector:
@@ -14,10 +18,14 @@ import { DaffPrefixDirective } from '@daffodil/design';
1418
templateUrl: './menu-item.component.html',
1519
styleUrls: ['./menu-item.component.scss'],
1620
changeDetection: ChangeDetectionStrategy.OnPush,
21+
standalone: true,
22+
imports: [
23+
NgIf,
24+
DaffPrefixSuffixModule,
25+
],
1726
})
1827

1928
export class DaffMenuItemComponent {
20-
2129
/**
2230
* @docs-private
2331
*/

libs/design/menu/src/menu.module.ts

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import { DaffMenuService } from './services/menu.service';
1111
imports: [
1212
CommonModule,
1313
OverlayModule,
14-
],
15-
declarations: [
1614
DaffMenuActivatorDirective,
1715
DaffMenuComponent,
1816
DaffMenuItemComponent,

libs/design/menu/src/menu/menu.component.spec.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
1212
import { BehaviorSubject } from 'rxjs';
1313

1414
import { DaffMenuComponent } from './menu.component';
15-
import { DaffMenuModule } from '../menu.module';
15+
import { DaffMenuItemComponent } from '../menu-item/menu-item.component';
1616
import { DaffMenuService } from '../services/menu.service';
1717
import { provideTestMenuService } from '../testing/dummy-service';
1818

19-
@Component({ template: `
20-
<daff-menu></daff-menu>
21-
` })
19+
@Component({
20+
template: `<daff-menu></daff-menu>`,
21+
standalone: true,
22+
imports: [
23+
DaffMenuComponent,
24+
DaffMenuItemComponent,
25+
],
26+
})
2227
class WrapperComponent {}
2328

2429
describe('@daffodil/design/menu | DaffMenuComponent', () => {
@@ -31,9 +36,6 @@ describe('@daffodil/design/menu | DaffMenuComponent', () => {
3136
TestBed.configureTestingModule({
3237
imports: [
3338
NoopAnimationsModule,
34-
DaffMenuModule,
35-
],
36-
declarations: [
3739
WrapperComponent,
3840
],
3941
providers: [

libs/design/menu/src/menu/menu.component.ts

+5
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@ import {
1818

1919
import { daffFocusableElementsSelector } from '@daffodil/design';
2020

21+
import { DaffMenuItemComponent } from '../menu-item/menu-item.component';
2122
import { DaffMenuService } from '../services/menu.service';
2223

2324
@Component({
2425
selector: 'daff-menu',
2526
template: '<ng-content select="[daff-menu-item]"></ng-content>',
2627
styleUrls: ['./menu.component.scss'],
2728
changeDetection: ChangeDetectionStrategy.OnPush,
29+
standalone: true,
30+
imports: [
31+
DaffMenuItemComponent,
32+
],
2833
})
2934
export class DaffMenuComponent implements AfterContentInit, AfterViewInit {
3035
@HostBinding('class.daff-menu') class = true;

libs/design/menu/src/services/menu.service.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import {
1010
ElementRef,
1111
Injectable,
12+
Injector,
1213
TemplateRef,
1314
Type,
1415
ViewContainerRef,
@@ -38,7 +39,10 @@ export class DaffMenuService {
3839
private $_open: BehaviorSubject<boolean> = new BehaviorSubject(false);
3940
public open$: Observable<boolean> = this.$_open.asObservable();
4041

41-
constructor(protected overlay: Overlay) {}
42+
constructor(
43+
protected overlay: Overlay,
44+
private injector: Injector,
45+
) {}
4246

4347
protected async _createOverlay(activatorElement: ViewContainerRef, component: DaffMenuSlot) {
4448
if (!this._overlay) {
@@ -48,9 +52,9 @@ export class DaffMenuService {
4852
}
4953

5054
if(component instanceof Type) {
51-
this._overlay.attach(new ComponentPortal(<Type<unknown>>component));
55+
this._overlay.attach(new ComponentPortal(<Type<unknown>>component, null, this.injector));
5256
} else if (component instanceof TemplateRef) {
53-
this._overlay.attach(new TemplatePortal(component, activatorElement));
57+
this._overlay.attach(new TemplatePortal(component, activatorElement, null, this.injector));
5458
}
5559

5660
this._overlay.backdropClick().pipe(

libs/design/menu/src/specs/children.spec.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ import { By } from '@angular/platform-browser';
1111
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
1212

1313
import { DaffMenuComponent } from '../menu/menu.component';
14-
import { DaffMenuModule } from '../menu.module';
15-
16-
@Component({ template: `
17-
<daff-menu></daff-menu>
18-
` })
14+
import { provideTestMenuService } from '../testing/dummy-service';
15+
16+
@Component({
17+
template: `<daff-menu></daff-menu>`,
18+
standalone: true,
19+
imports: [
20+
DaffMenuComponent,
21+
],
22+
})
1923
class WrapperComponent {}
2024

2125
describe('@daffodil/design/menu | DaffMenuComponent', () => {
@@ -28,11 +32,11 @@ describe('@daffodil/design/menu | DaffMenuComponent', () => {
2832
TestBed.configureTestingModule({
2933
imports: [
3034
NoopAnimationsModule,
31-
DaffMenuModule,
32-
],
33-
declarations: [
3435
WrapperComponent,
3536
],
37+
providers: [
38+
provideTestMenuService(),
39+
],
3640
})
3741
.compileComponents();
3842
}));

libs/design/menu/src/specs/no-children.spec.ts

+20-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { OverlayModule } from '@angular/cdk/overlay';
21
import {
32
Component,
43
DebugElement,
@@ -12,14 +11,22 @@ import { By } from '@angular/platform-browser';
1211
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
1312

1413
import { DaffMenuComponent } from '../menu/menu.component';
15-
import { DaffMenuModule } from '../menu.module';
16-
17-
@Component({ template: `
18-
<daff-menu>
19-
<a href="/test" daff-menu-item id="focused">Test</a>
20-
<button daff-menu-item id="not-focused">Test 2</button>
21-
</daff-menu>
22-
` })
14+
import { DaffMenuItemComponent } from '../menu-item/menu-item.component';
15+
import { provideTestMenuService } from '../testing/dummy-service';
16+
17+
@Component({
18+
template: `
19+
<daff-menu>
20+
<a href="/test" daff-menu-item id="focused">Test</a>
21+
<button daff-menu-item id="not-focused">Test 2</button>
22+
</daff-menu>
23+
`,
24+
standalone: true,
25+
imports: [
26+
DaffMenuComponent,
27+
DaffMenuItemComponent,
28+
],
29+
})
2330
class WrapperComponent {}
2431

2532
describe('@daffodil/design/menu | DaffMenuComponent', () => {
@@ -32,11 +39,11 @@ describe('@daffodil/design/menu | DaffMenuComponent', () => {
3239
TestBed.configureTestingModule({
3340
imports: [
3441
NoopAnimationsModule,
35-
DaffMenuModule,
36-
],
37-
declarations: [
3842
WrapperComponent,
3943
],
44+
providers: [
45+
provideTestMenuService(),
46+
],
4047
})
4148
.compileComponents();
4249
}));
@@ -55,8 +62,6 @@ describe('@daffodil/design/menu | DaffMenuComponent', () => {
5562
});
5663

5764
it('should focus the first focusable child', () => {
58-
expect(
59-
document.activeElement === de.query(By.css('#focused')).nativeElement,
60-
).toEqual(true);
65+
expect(document.activeElement === de.query(By.css('#focused')).nativeElement).toEqual(true);
6166
});
6267
});

0 commit comments

Comments
 (0)