Skip to content

Commit 222086d

Browse files
fix(menu): fix menu & submenu trigger issue
1 parent 2a4af79 commit 222086d

File tree

5 files changed

+67
-24
lines changed

5 files changed

+67
-24
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@ng-icons/lucide": "^31.4.0",
3131
"@tailwindcss/postcss": "^4.0.15",
3232
"express": "^4.18.2",
33-
"ng-primitives": "^0.44.0",
33+
"ng-primitives": "^0.46.0",
3434
"ngx-highlightjs": "^14.0.0",
3535
"postcss": "^8.5.3",
3636
"rxjs": "~7.8.0",
@@ -58,4 +58,4 @@
5858
"tw-animate-css": "^1.3.0",
5959
"typescript": "~5.7.2"
6060
}
61-
}
61+
}

projects/core/src/lib/menu.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { computed, Directive, effect, input, TemplateRef } from '@angular/core';
2-
import { NgpMenu, NgpMenuItem, NgpMenuTrigger } from "ng-primitives/menu";
3-
import { injectPopoverTriggerState } from 'ng-primitives/popover';
2+
import { NgpMenu, NgpMenuItem, NgpMenuTrigger, NgpSubmenuTrigger } from "ng-primitives/menu";
43
import { tv } from 'tailwind-variants';
54

65
const menuVariants = tv({
76
slots: {
8-
base: 'absolute bg-popover text-popover-foreground data-[enter]:animate-in data-[exit]:animate-out data-[exit]:fade-out-0 data-[enter]:fade-in-0 data-[exit]:zoom-out-95 data-[enter]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--ngp-popover-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border border-border p-1 shadow-md',
9-
itemVariant: "w-full data-[focus-visible]:bg-accent data-[focus-visible]:text-accent-foreground data-[hover]:bg-accent data-[hover]:text-accent-foreground relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7+
base: 'absolute bg-popover text-popover-foreground data-[enter]:animate-in data-[exit]:animate-out data-[exit]:fade-out-0 data-[enter]:fade-in-0 data-[exit]:zoom-out-95 data-[enter]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--ngp-menu-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border border-border p-1 shadow-md',
8+
itemVariant: "w-full data-[focus-visible]:bg-accent data-[focus-visible]:text-accent-foreground data-[hover]:bg-accent data-[hover]:text-accent-foreground data-[open]:bg-accent data-[open]:text-accent-foreground relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
109
shortcutVariant: 'text-muted-foreground ml-auto text-xs tracking-widest',
1110
separatorVariant: 'bg-border -mx-1 my-1 h-px',
12-
labelVariant: 'px-2 py-1.5 text-sm font-medium data-[inset]:pl-8',
11+
labelVariant: 'px-2 py-1.5 text-sm font-medium data-[inset]:pl-8'
1312
}
1413
});
1514

@@ -31,16 +30,12 @@ export class UiMenu {
3130
@Directive({
3231
selector: '[uiMenuTrigger]',
3332
exportAs: 'uiMenuTrigger',
34-
hostDirectives: [NgpMenuTrigger],
33+
hostDirectives: [{
34+
directive: NgpMenuTrigger,
35+
inputs: ['ngpMenuTrigger: uiMenuTrigger']
36+
}],
3537
})
3638
export class UiMenuTrigger {
37-
private readonly state = injectPopoverTriggerState();
38-
readonly trigger = input.required<TemplateRef<any>>({
39-
alias: 'uiMenuTrigger',
40-
});
41-
constructor() {
42-
effect(() => this.state().popover.set(this.trigger()));
43-
}
4439
}
4540

4641
@Directive({
@@ -90,4 +85,17 @@ export class UiMenuLabel {
9085
export class UiMenuItem {
9186
inputClass = input<string>('', { alias: 'class' });
9287
computedClass = computed(() => itemVariant({ class: this.inputClass() }));
88+
}
89+
90+
@Directive({
91+
selector: '[uiSubmenuTrigger]',
92+
exportAs: 'uiSubmenuTrigger',
93+
hostDirectives: [{
94+
directive: NgpSubmenuTrigger,
95+
inputs: ['ngpSubmenuTrigger: uiSubmenuTrigger']
96+
}],
97+
})
98+
export class UiSubmenuTrigger {
99+
inputClass = input<string>('', { alias: 'class' });
100+
computedClass = computed(() => itemVariant({ class: this.inputClass() }));
93101
}

projects/docs/src/app/pages/docs/components/dropdown-menu/dropdown-menu.component.html

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ <h1 class="text-2xl font-semibold">Dropdown Menu</h1>
2626
<button uiMenuItem disabled>API</button>
2727
<div uiMenuSeparator></div>
2828
<button uiMenuItem>Logout <div uiMenuShortcut>⇧⌘Q</div></button>
29-
3029
</div>
3130
</ng-template>
3231
</docs-example>
@@ -39,4 +38,37 @@ <h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="in
3938
<h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="usage">Usage</h2>
4039

4140
<docs-code-view [code]="importCode"></docs-code-view>
42-
<docs-code-view class="mt-5 block" [code]="usageCode" language="html"></docs-code-view>
41+
<docs-code-view class="mt-5 block" [code]="usageCode" language="html"></docs-code-view>
42+
43+
<h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="examples">Examples</h2>
44+
45+
<div class="mt-5">
46+
<h3 class="text-lg font-semibold mb-3" id="default">Default</h3>
47+
<docs-example [code]="AVATAR_CODES.DEFAULT">
48+
<button uiButton variant="outline" [uiMenuTrigger]="menu1">Open</button>
49+
<ng-template #menu1>
50+
<div uiMenu class="w-56">
51+
<div uiMenuLabel>My Account</div>
52+
<div uiMenuSeparator></div>
53+
<button uiMenuItem>Profile <div uiMenuShortcut>⇧⌘P</div></button>
54+
<button uiMenuItem>Billing <div uiMenuShortcut>⌘B</div></button>
55+
<button uiMenuItem>Settings <div uiMenuShortcut>⌘S</div></button>
56+
<button uiMenuItem>Keyboard shortcuts <div uiMenuShortcut>⌘K</div></button>
57+
<div uiMenuSeparator></div>
58+
<button uiMenuItem>Github</button>
59+
<button uiMenuItem>Support</button>
60+
<button uiMenuItem [uiSubmenuTrigger]="submenu">API <div uiMenuShortcut><ng-icon
61+
name="bootstrapChevronRight" /></div></button>
62+
<div uiMenuSeparator></div>
63+
<button uiMenuItem>Logout <div uiMenuShortcut>⇧⌘Q</div></button>
64+
</div>
65+
</ng-template>
66+
<ng-template #submenu>
67+
<div uiMenu>
68+
<button uiMenuItem>Item 1</button>
69+
<button uiMenuItem>Item 2</button>
70+
<button uiMenuItem>Item 3</button>
71+
</div>
72+
</ng-template>
73+
</docs-example>
74+
</div>

projects/docs/src/app/pages/docs/components/dropdown-menu/dropdown-menu.component.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { Component } from '@angular/core';
22
import { AvatarCodeConstants } from './dropdown-menu.constants';
3-
import { UiMenu, UiMenuTrigger, UiMenuItem, UiMenuLabel, UiMenuSeparator, UiMenuShortcut, UiButton } from '@angularui/core';
3+
import { UiMenu, UiMenuTrigger, UiMenuItem, UiMenuLabel, UiMenuSeparator, UiMenuShortcut, UiButton, UiSubmenuTrigger } from '@angularui/core';
44
import { InstallationGuideComponent } from '../../../../components/installation-guide/installation-guide.component';
55
import { CodeViewComponent } from '../../../../components/code-view/code-view.component';
66
import { ExampleComponent } from '../../../../components/example/example.component';
7+
import { NgIcon, provideIcons } from '@ng-icons/core';
8+
import { bootstrapChevronRight } from '@ng-icons/bootstrap-icons';
79

810
@Component({
911
selector: 'docs-dropdown-menu',
10-
imports: [ExampleComponent, CodeViewComponent, InstallationGuideComponent, UiMenu, UiMenuTrigger, UiMenuItem, UiMenuLabel, UiMenuSeparator, UiMenuShortcut, UiButton],
11-
templateUrl: './dropdown-menu.component.html'
12+
imports: [ExampleComponent, CodeViewComponent, InstallationGuideComponent, UiMenu, UiMenuTrigger, UiMenuItem, UiMenuLabel, UiMenuSeparator, UiMenuShortcut, UiSubmenuTrigger, UiButton, NgIcon],
13+
templateUrl: './dropdown-menu.component.html',
14+
viewProviders: [provideIcons({ bootstrapChevronRight })],
1215
})
1316
export class DropdownMenuComponent {
1417
importCode = `import { AvatarDirective, AvatarFallbackDirective, AvatarImageDirective } from '@angularui/core';`

0 commit comments

Comments
 (0)