Skip to content

Commit 6ba1c83

Browse files
Mohammad JavedMohammad Javed
Mohammad Javed
authored and
Mohammad Javed
committed
feat(Popover): Added Popover component
1 parent 7f261c4 commit 6ba1c83

File tree

8 files changed

+200
-2
lines changed

8 files changed

+200
-2
lines changed

projects/core/src/lib/popover.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { computed, Directive, effect, input, TemplateRef } from "@angular/core";
2+
import { tv } from "tailwind-variants";
3+
import { injectPopoverTriggerState, NgpPopover, NgpPopoverTrigger } from "ng-primitives/popover";
4+
const popoverVariants = tv({
5+
base: 'bg-popover absolute 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 w-72 origin-(--ngp-popover-transform-origin) rounded-md border border-border p-4 shadow-md outline-hidden'
6+
})
7+
8+
@Directive({
9+
selector: '[uiPopover]',
10+
exportAs: 'uiPopover',
11+
host: {
12+
'[class]': 'computedClass()'
13+
},
14+
hostDirectives: [NgpPopover],
15+
})
16+
17+
export class UiPopover {
18+
inputClass = input<string>('', { alias: 'class' });
19+
computedClass = computed(() => popoverVariants({ class: this.inputClass() }));
20+
}
21+
22+
@Directive({
23+
selector: '[uiPopoverTrigger]',
24+
exportAs: 'uiPopoverTrigger',
25+
hostDirectives: [{
26+
directive: NgpPopoverTrigger,
27+
inputs: ['ngpPopoverTriggerDisabled: uiPopoverTriggerDisabled, ngpPopoverTriggerPlacement: uiPopoverTriggerPlacement, ngpPopoverTriggerOffset: uiPopoverTriggerOffset, ngpPopoverTriggerShowDelay: uiPopoverTriggerShowDelay, ngpPopoverTriggerHideDelay: uiPopoverTriggerHideDelay, ngpPopoverTriggerFlip: uiPopoverTriggerFlip, ngpPopoverTriggerContainer: uiPopoverTriggerContainer, ngpPopoverTriggerCloseOnOutsideClick: uiPopoverTriggerCloseOnOutsideClick, ngpPopoverTriggerCloseOnEscape: uiPopoverTriggerCloseOnEscape, ngpPopoverTriggerScrollBehavior: uiPopoverTriggerScrollBehavior, ngpPopoverTriggerContext: uiPopoverTriggerContext'],
28+
}],
29+
})
30+
export class UiPopoverTrigger {
31+
inputClass = input<string>('', { alias: 'class' });
32+
computedClass = computed(() => popoverVariants({ class: this.inputClass() }));
33+
private readonly state = injectPopoverTriggerState();
34+
35+
readonly trigger = input.required<TemplateRef<any>>({
36+
alias: 'uiPopoverTrigger',
37+
});
38+
39+
constructor() {
40+
effect(() => this.state().popover.set(this.trigger()));
41+
}
42+
}

projects/core/src/public-api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export * from './lib/menu';
55
export * from './lib/accordion';
66
export * from './lib/tabs';
77
export * from './lib/badge';
8-
export * from './lib/dialog';
8+
export * from './lib/dialog';
9+
export * from './lib/popover';

projects/docs/src/app/app.routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export const routes: Routes = [
4141
path: 'components/dropdown-menu',
4242
loadComponent: () => import('./pages/docs/components/dropdown-menu/dropdown-menu.component').then(c => c.DropdownMenuComponent)
4343
},
44+
{
45+
path: 'components/popover',
46+
loadComponent: () => import('./pages/docs/components/popover/popover.component').then(c => c.PopoverComponent)
47+
},
4448
{
4549
path: '',
4650
pathMatch: 'full',

projects/docs/src/app/components/sidenav/sidenav.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ export class SidenavComponent {
3333
{ name: 'Badge', path: '/docs/components/badge' },
3434
{ name: 'Button', path: '/docs/components/button' },
3535
{ name: 'Dialog', path: '/docs/components/dialog' },
36-
{ name: 'Dropdown Menu', path: '/docs/components/dropdown-menu' }
36+
{ name: 'Dropdown Menu', path: '/docs/components/dropdown-menu' },
37+
{ name: 'Popver', path: '/docs/components/popover' }
3738
]
3839
}
3940
];
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<p
2+
class="from-indigo-700 to-blue-500 mb-2 inline-block bg-gradient-to-r bg-clip-text text-sm font-medium text-transparent">
3+
Components
4+
</p>
5+
<h1 class="text-2xl font-semibold">Popover</h1>
6+
7+
<p class="mt-4 text-md text-muted-foreground">
8+
Displays rich content in a portal, triggered by a button.
9+
</p>
10+
11+
12+
<div class="mt-5">
13+
<docs-example [code]="POPOVER_CODES.DEFAULT">
14+
<button [uiPopoverTrigger]="popover" uiButton variant="outline">
15+
Popover
16+
</button>
17+
18+
<ng-template #popover>
19+
<div uiPopover>
20+
<h3>Need Help?</h3>
21+
<p>
22+
Get quick tips and guidance on how to use this feature effectively.
23+
Check out our documentation for more details!
24+
</p>
25+
26+
<a target="_blank" href="https://www.youtube.com/watch?v=xvFZjo5PgG0">Learn More</a>
27+
</div>
28+
</ng-template>
29+
</docs-example>
30+
</div>
31+
32+
33+
<h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="installation">Installation</h2>
34+
<docs-installation-guide [cliCode]="cliCode" [npmCode]="POPOVER_CODES.DEFAULT"></docs-installation-guide>
35+
36+
<h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="usage">Usage</h2>
37+
38+
<docs-code-view [code]="importCode"></docs-code-view>
39+
<docs-code-view class="mt-5 block" [code]="usageCode" language="html"></docs-code-view>
40+
41+
<h2 class="text-xl font-semibold my-5 border-b border-border pb-3 mt-10" id="examples">Examples</h2>
42+
43+
<div class="mt-5">
44+
<h3 class="text-lg font-semibold mb-3" id="default">Default</h3>
45+
<docs-example [code]="POPOVER_CODES.DEFAULT">
46+
<button [uiPopoverTrigger]="popover" uiButton variant="outline">
47+
Popover
48+
</button>
49+
50+
<ng-template #popover>
51+
<div uiPopover>
52+
<h3>Need Help?</h3>
53+
<p>
54+
Get quick tips and guidance on how to use this feature effectively.
55+
Check out our documentation for more details!
56+
</p>
57+
58+
<a target="_blank" href="https://www.youtube.com/watch?v=xvFZjo5PgG0">Learn More</a>
59+
</div>
60+
</ng-template>
61+
</docs-example>
62+
</div>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Component } from '@angular/core';
2+
import { ExampleComponent } from '../../../../components/example/example.component';
3+
import { CodeViewComponent } from '../../../../components/code-view/code-view.component';
4+
import { InstallationGuideComponent } from '../../../../components/installation-guide/installation-guide.component';
5+
import { UiButton, UiPopover, UiPopoverTrigger } from '@angularui/core';
6+
import { PopoverCodeConstants } from './popover.constants';
7+
8+
@Component({
9+
selector: 'docs-popover',
10+
imports: [ExampleComponent, CodeViewComponent, InstallationGuideComponent, UiPopover, UiPopoverTrigger, UiButton],
11+
templateUrl: './popover.component.html'
12+
})
13+
export class PopoverComponent {
14+
15+
importCode = `import { UiButton, UiPopover, UiPopoverTrigger } from '@angularui/core';`
16+
usageCode = `
17+
<button [uiPopoverTrigger]="popover" uiButton variant="outline">
18+
Popover
19+
</button>
20+
21+
<ng-template #popover>
22+
<div uiPopover>
23+
<h3>Need Help?</h3>
24+
<p>
25+
Get quick tips and guidance on how to use this feature effectively.
26+
Check out our documentation for more details!
27+
</p>
28+
</div>
29+
</ng-template>`;
30+
31+
cliCode = `ng g @angularui/core:component popover`;
32+
33+
POPOVER_CODES = PopoverCodeConstants;
34+
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export class PopoverCodeConstants {
2+
static readonly DEFAULT = `
3+
import { Component } from '@angular/core';
4+
import { UiButton, UiPopover, UiPopoverTrigger } from '@angularui/core';
5+
6+
@Component({
7+
selector: 'popover-demo',
8+
imports: [UiButton, UiPopover, UiPopoverTrigger],
9+
template: \` <button [uiPopoverTrigger]="popover" uiButton variant="outline">
10+
Popover
11+
</button>
12+
13+
<ng-template #popover>
14+
<div uiPopover>
15+
<h3>Need Help?</h3>
16+
<p>
17+
Get quick tips and guidance on how to use this feature effectively.
18+
Check out our documentation for more details!
19+
</p>
20+
</div>
21+
</ng-template> \`
22+
})
23+
export class PopoverComponent {}
24+
`;
25+
}

projects/docs/src/styles.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,34 @@
6363
height: 0;
6464
}
6565
}
66+
67+
--animate-in: in 0.2s ease-in-out forwards;
68+
69+
@keyframes in {
70+
0% {
71+
opacity: 0;
72+
transform: scale(0.9);
73+
}
74+
75+
100% {
76+
opacity: 1;
77+
transform: scale(1);
78+
}
79+
}
80+
81+
--animate-out: out 0.2s ease-in-out forwards;
82+
83+
@keyframes out {
84+
0% {
85+
opacity: 1;
86+
transform: scale(1);
87+
}
88+
89+
100% {
90+
opacity: 0;
91+
transform: scale(0.9);
92+
}
93+
}
6694
}
6795

6896
.dark {

0 commit comments

Comments
 (0)