Skip to content

Commit 13799a5

Browse files
tibing-old-emailnnixaa
authored andcommitted
feat(context-menu): add context menu component
1 parent 959bd4a commit 13799a5

19 files changed

+387
-6
lines changed

docs/articles/concept-ui-kit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Here's a list of Nebular components:
1212
- [User(Avatar)](#/docs/components/user-avatar)
1313
- [Checkbox](#/docs/components/checkbox)
1414
- [Popover](#/docs/components/popover)
15+
- [Context Menu](#/docs/components/context-menu)
1516
<hr class="section-end">
1617

1718
<div class="note note-success">
60.7 KB
Loading

docs/structure.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,22 @@ export const STRUCTURE = [
410410
},
411411
],
412412
},
413+
{
414+
type: 'page',
415+
name: 'Context Menu',
416+
children: [
417+
{
418+
type: 'block',
419+
block: 'component',
420+
blockData: 'NbContextMenuDirective',
421+
},
422+
{
423+
type: 'block',
424+
block: 'component',
425+
blockData: 'NbContextMenuComponent',
426+
},
427+
],
428+
},
413429
],
414430
},
415431
{

e2e/context-menu.e2e-spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { browser, by, element } from 'protractor';
2+
3+
const withContextMenu = by.css('nb-card:nth-child(1) nb-user:nth-child(1)');
4+
const popover = by.css('nb-layout > nb-popover');
5+
6+
describe('nb-context-menu', () => {
7+
8+
beforeEach((done) => {
9+
browser.get('#/context-menu').then(done);
10+
});
11+
12+
it('have to be opened by click', () => {
13+
element(withContextMenu).click();
14+
const containerContent = element(popover).element(by.css('nb-menu > ul'));
15+
expect(containerContent.isPresent()).toBeTruthy();
16+
});
17+
18+
it('should have two menu items', () => {
19+
element(withContextMenu).click();
20+
const menuItems = element(popover).all(by.css('nb-menu > ul > li'));
21+
22+
expect(menuItems.count()).toEqual(2);
23+
});
24+
25+
it('have to open user page after click on first item', () => {
26+
element(withContextMenu).click();
27+
const menuItems = element(popover).all(by.css('nb-menu > ul > li'));
28+
menuItems.get(0).click();
29+
30+
expect(browser.getCurrentUrl().then(it => it.split('#/')[1])).toEqual('user');
31+
});
32+
33+
it('have to open popover page after click on second item', () => {
34+
element(withContextMenu).click();
35+
const menuItems = element(popover).all(by.css('nb-menu > ul > li'));
36+
menuItems.get(1).click();
37+
38+
expect(browser.getCurrentUrl().then(it => it.split('#/')[1])).toEqual('popover');
39+
});
40+
});

src/app/app.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
NbThemeModule,
2424
NbUserModule,
2525
NbPopoverModule,
26+
NbContextMenuModule,
2627
} from '@nebular/theme';
2728

2829
import {
@@ -69,6 +70,7 @@ import { NbDynamicToAddComponent, NbThemeDynamicTestComponent } from './layout-t
6970
import { NbActionsTestComponent } from './actions-test/actions-test.component';
7071
import { NbBootstrapTestComponent } from './bootstrap-test/bootstrap-test.component';
7172
import { NbPopoverTestComponent } from './popover-test/popover-test.component';
73+
import { NbContextMenuTestComponent } from './context-menu-test/context-menu-test.component';
7274

7375
import { routes } from './app.routes';
7476

@@ -119,6 +121,7 @@ const NB_TEST_COMPONENTS = [
119121
NbPopoverTestComponent,
120122
NbCheckboxTestComponent,
121123
NbAclTestComponent,
124+
NbContextMenuTestComponent,
122125
];
123126

124127
@NgModule({
@@ -138,6 +141,7 @@ const NB_TEST_COMPONENTS = [
138141
NbSearchModule,
139142
NbActionsModule,
140143
NbPopoverModule,
144+
NbContextMenuModule,
141145
NbCheckboxModule,
142146
NbAuthModule.forRoot({
143147
forms: {

src/app/app.routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
import { AuthGuard } from './auth-guard.service';
5454
import { NbCheckboxTestComponent } from './checkbox-test/checkbox-test.component';
5555
import { NbAclTestComponent } from './acl-test/acl-test.component';
56+
import { NbContextMenuTestComponent } from './context-menu-test/context-menu-test.component';
5657

5758
export const routes: Routes = [
5859
{
@@ -258,6 +259,10 @@ export const routes: Routes = [
258259
path: 'acl',
259260
component: NbAclTestComponent,
260261
},
262+
{
263+
path: 'context-menu',
264+
component: NbContextMenuTestComponent,
265+
},
261266
{
262267
path: '**',
263268
component: NbCardTestComponent,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'nb-context-menu-test',
5+
template: `
6+
<nb-layout>
7+
<nb-layout-column>
8+
<nb-card>
9+
<nb-card-header>Context Menu</nb-card-header>
10+
<nb-card-body>
11+
<nb-user name="Nikita Poltoratsky" title="full-stack developer" [nbContextMenu]="items">
12+
</nb-user>
13+
</nb-card-body>
14+
</nb-card>
15+
16+
<nb-card>
17+
<nb-card-header>Context Menu</nb-card-header>
18+
<nb-card-body>
19+
<nb-user name="Nikita Poltoratsky" title="full-stack developer" [nbContextMenu]="itemsWithIcons">
20+
</nb-user>
21+
</nb-card-body>
22+
</nb-card>
23+
</nb-layout-column>
24+
</nb-layout>
25+
`,
26+
})
27+
export class NbContextMenuTestComponent {
28+
29+
items = [
30+
{ title: 'Profile', link: '/user' },
31+
{ title: 'Logout', link: '/popover' },
32+
];
33+
34+
itemsWithIcons = [
35+
{ title: 'Profile', link: '/user', icon: 'nb-compose' },
36+
{ title: 'Logout', link: '/popover', icon: 'nb-gear' },
37+
];
38+
}

src/app/popover-test/popover-test.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,6 @@ import { NbDynamicToAddComponent } from '../layout-test/theme-dynamic-test.compo
152152
export class NbPopoverTestComponent {
153153

154154
customPopoverComponent = NbDynamicToAddComponent;
155+
156+
items = [{ title: 'Profile', link: '/card' }, { title: 'Log out', link: '/auth' }];
155157
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license
3+
* Copyright Akveo. All Rights Reserved.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
@import '../../styles/core/mixins';
8+
9+
@mixin nb-context-menu-theme() {
10+
nb-menu.context-menu .menu-items .menu-item a {
11+
color: nb-theme(context-menu-fg);
12+
font-weight: nb-theme(font-weight-normal);
13+
14+
.menu-icon {
15+
color: nb-theme(context-menu-fg);
16+
}
17+
18+
@include hover-focus-active {
19+
color: nb-theme(context-menu-active-fg);
20+
background: nb-theme(context-menu-active-bg);
21+
font-weight: nb-theme(font-weight-normal);
22+
23+
.menu-icon {
24+
color: nb-theme(context-menu-active-fg);
25+
}
26+
}
27+
}
28+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @license
3+
* Copyright Akveo. All Rights Reserved.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
:host /deep/ nb-menu {
8+
display: inline;
9+
font-size: 0.875rem;
10+
line-height: 1.5rem;
11+
12+
ul.menu-items {
13+
margin: 0;
14+
padding: 0.5rem 0;
15+
16+
.menu-item {
17+
border: none;
18+
white-space: nowrap;
19+
20+
&:first-child {
21+
border: none;
22+
}
23+
24+
a {
25+
cursor: pointer;
26+
border-radius: 0;
27+
padding: 0;
28+
29+
.menu-icon {
30+
font-size: 1.5rem;
31+
width: auto;
32+
}
33+
34+
.menu-title {
35+
padding: 0.375rem 3rem;
36+
}
37+
38+
.menu-icon ~ .menu-title {
39+
padding-left: 0;
40+
}
41+
42+
.menu-icon:first-child {
43+
padding-left: 1rem;
44+
}
45+
}
46+
}
47+
}
48+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license
3+
* Copyright Akveo. All Rights Reserved.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*/
6+
7+
import { Component, Input } from '@angular/core';
8+
import { NbMenuItem } from '../../';
9+
10+
/**
11+
* Context menu component used as content within NbContextMenuDirective.
12+
*
13+
* @styles
14+
*
15+
* context-menu-fg
16+
* context-menu-active-fg
17+
* context-menu-active-bg
18+
* */
19+
@Component({
20+
selector: 'nb-context-menu',
21+
styleUrls: ['./context-menu.component.scss'],
22+
template: '<nb-menu class="context-menu" [items]="items"></nb-menu>',
23+
})
24+
export class NbContextMenuComponent {
25+
26+
@Input()
27+
items: NbMenuItem[] = [];
28+
}

0 commit comments

Comments
 (0)