Skip to content

Commit

Permalink
feat(badge): dot mode (#2479)
Browse files Browse the repository at this point in the history
  • Loading branch information
maksim-karatkevich authored Sep 17, 2020
1 parent 70ee391 commit afe02b7
Show file tree
Hide file tree
Showing 26 changed files with 284 additions and 17 deletions.
12 changes: 12 additions & 0 deletions src/app/playground-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [
component: 'ActionWidthComponent',
name: 'Action Width',
},
{
path: 'action-dot-mode.component',
link: '/action/action-dot-mode.component',
component: 'ActionDotModeComponent',
name: 'Action Dot Mode',
},
],
},
{
Expand Down Expand Up @@ -724,6 +730,12 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [
component: 'MenuLinkParamsComponent',
name: 'Menu Link Params',
},
{
path: 'menu-badge.component',
link: '/menu/menu-badge.component',
component: 'MenuBadgeComponent',
name: 'Menu Badge',
},
{
path: 'menu-service.component',
link: '/menu/menu-service.component',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
}
}


nb-action {
$divider: nb-theme(actions-divider-width) nb-theme(actions-divider-style) nb-theme(actions-divider-color);
@include nb-ltr(border-left, $divider);
@include nb-rtl(border-right, $divider);

&:first-child {
@include nb-ltr(border-left, none!important);
@include nb-rtl(border-right, none!important);
@include nb-ltr(border-left, none !important);
@include nb-rtl(border-right, none !important);
}

nb-icon {
Expand Down
2 changes: 2 additions & 0 deletions src/framework/theme/components/actions/action.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
}

a.icon-container {
position: relative;

&:hover, &:focus {
text-decoration: none;
}
Expand Down
35 changes: 29 additions & 6 deletions src/framework/theme/components/actions/actions.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,37 @@ import { NbIconConfig } from '../icon/icon.component';
[title]="title"
*ngIf="link">
<nb-icon [config]="icon"></nb-icon>
<ng-container [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
<a class="icon-container"
[href]="href"
[title]="title"
*ngIf="href && !link">
<nb-icon [config]="icon"></nb-icon>
<ng-container [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
<a class="icon-container"
href="#"
[title]="title"
*ngIf="!href && !link"
(click)="$event.preventDefault()">
<nb-icon [config]="icon"></nb-icon>
<ng-container [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
</ng-container>
<ng-template #projectedContent>
<ng-content></ng-content>
<ng-container [ngTemplateOutlet]="badgeTemplate"></ng-container>
</ng-template>
<ng-template #badgeTemplate>
<nb-badge *ngIf="badgeText || badgeDot"
[text]="badgeText"
[dotMode]="badgeDot"
[status]="badgeStatus"
[position]="badgePosition">
</nb-badge>
</ng-template>
<nb-badge *ngIf="badgeText"
[text]="badgeText"
[status]="badgeStatus"
[position]="badgePosition">
</nb-badge>
`,
})
export class NbActionComponent {
Expand Down Expand Up @@ -93,6 +99,20 @@ export class NbActionComponent {
protected _disabled: boolean = false;
static ngAcceptInputType_disabled: NbBooleanInput;

/**
* Use badge dot mode
* @type boolean
*/
@Input()
get badgeDot(): boolean {
return this._badgeDot;
}
set badgeDot(value: boolean) {
this._badgeDot = convertToBoolProperty(value);
}
protected _badgeDot: boolean;
static ngAcceptInputType_badgeDot: NbBooleanInput;

/**
* Badge text to display
* @type string
Expand Down Expand Up @@ -154,6 +174,9 @@ export class NbActionComponent {
* and we can set it to full a width of a parent component
* @stacked-example(Full Width, action/action-width.component)
*
* Action dot mode
* @stacked-example(Action badge in dot mode, action/action-dot-mode.component)
*
* @styles
*
* actions-background-color:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
font-weight: nb-theme(badge-text-font-weight);
line-height: nb-theme(badge-text-line-height);
padding: nb-theme(badge-padding);

&.dot-mode {
padding: nb-theme(badge-dot-mode-padding);
border-radius: nb-theme(badge-dot-mode-border-radius);
}
}

@each $status in nb-get-statuses() {
Expand Down
5 changes: 5 additions & 0 deletions src/framework/theme/components/badge/badge.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
left: 0;
}

:host(.position-center) {
top: 50%;
transform: translateY(-50%);
}

:host(.position-start) {
@include nb-ltr(left, 0);
@include nb-rtl(right, 0);
Expand Down
35 changes: 30 additions & 5 deletions src/framework/theme/components/badge/badge.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
import { Component, HostBinding, Input } from '@angular/core';

import { NbComponentStatus } from '../component-status';
import { emptyStatusWarning } from '../helpers';
import { convertToBoolProperty, emptyStatusWarning } from '../helpers';

export type NbBadgePhysicalPosition = 'top left' | 'top right' | 'bottom left' | 'bottom right';
export type NbBadgeLogicalPosition = 'top start' | 'top end' | 'bottom start' | 'bottom end';
export type NbBadgePhysicalPosition = 'top left' | 'top right' | 'bottom left' | 'bottom right' | 'center right' | 'center left';
export type NbBadgeLogicalPosition = 'top start' | 'top end' | 'bottom start' | 'bottom end' | 'center start'| 'center end';
export type NbBadgePosition = NbBadgePhysicalPosition | NbBadgeLogicalPosition;

export interface NbBadge {
text?: string;
position?: NbBadgePosition;
status?: NbComponentStatus;
dotMode?: boolean;
}

/**
* Badge is a simple labeling component.
Expand Down Expand Up @@ -79,9 +85,9 @@ export type NbBadgePosition = NbBadgePhysicalPosition | NbBadgeLogicalPosition;
@Component({
selector: 'nb-badge',
styleUrls: ['./badge.component.scss'],
template: `{{text}}`,
template: `{{dotMode ? '' : text}}`,
})
export class NbBadgeComponent {
export class NbBadgeComponent implements NbBadge {

/**
* Text to display
Expand All @@ -107,6 +113,20 @@ export class NbBadgeComponent {
protected _defaultPosition: NbBadgePosition = 'top right';
protected _position: NbBadgePosition = this._defaultPosition;

/**
* Shows badge as a dot. No text is shown.
* @type boolean
*/
@Input()
@HostBinding('class.dot-mode')
get dotMode(): boolean {
return this._dotMode;
}
set dotMode(value: boolean) {
this._dotMode = convertToBoolProperty(value);
}
protected _dotMode: boolean;

/**
* Badge status (adds specific styles):
* 'basic', 'primary', 'info', 'success', 'warning', 'danger', 'control'
Expand Down Expand Up @@ -188,4 +208,9 @@ export class NbBadgeComponent {
get end(): boolean {
return this.position.includes('end');
}

@HostBinding('class.position-center')
get center(): boolean {
return this.position.includes('center');
}
}
10 changes: 10 additions & 0 deletions src/framework/theme/components/menu/menu-item.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
(click)="onItemClick(menuItem);">
<nb-icon class="menu-icon" [config]="menuItem.icon" *ngIf="menuItem.icon"></nb-icon>
<span class="menu-title">{{ menuItem.title }}</span>
<ng-container *ngIf="badge" [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
<a *ngIf="menuItem.url && !menuItem.children && !menuItem.link && !menuItem.group"
[attr.href]="menuItem.url"
Expand All @@ -24,6 +25,7 @@
(click)="onSelectItem(menuItem)">
<nb-icon class="menu-icon" [config]="menuItem.icon" *ngIf="menuItem.icon"></nb-icon>
<span class="menu-title">{{ menuItem.title }}</span>
<ng-container *ngIf="badge" [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
<a *ngIf="!menuItem.children && !menuItem.link && !menuItem.url && !menuItem.group"
[attr.target]="menuItem.target"
Expand All @@ -33,6 +35,7 @@
(click)="$event.preventDefault(); onItemClick(menuItem);">
<nb-icon class="menu-icon" [config]="menuItem.icon" *ngIf="menuItem.icon"></nb-icon>
<span class="menu-title">{{ menuItem.title }}</span>
<ng-container *ngIf="badge" [ngTemplateOutlet]="badgeTemplate"></ng-container>
</a>
<a *ngIf="menuItem.children"
(click)="$event.preventDefault(); onToggleSubMenu(menuItem);"
Expand All @@ -43,6 +46,7 @@
href="#">
<nb-icon class="menu-icon" [config]="menuItem.icon" *ngIf="menuItem.icon"></nb-icon>
<span class="menu-title">{{ menuItem.title }}</span>
<ng-container *ngIf="badge" [ngTemplateOutlet]="badgeTemplate"></ng-container>
<nb-icon class="expand-state" [icon]="getExpandStateIcon()" pack="nebular-essentials"></nb-icon>
</a>
<ul *ngIf="menuItem.children"
Expand All @@ -53,6 +57,7 @@
<ng-container *ngFor="let item of menuItem.children">
<li nbMenuItem *ngIf="!item.hidden"
[menuItem]="item"
[badge]="item.badge"
[class.menu-group]="item.group"
(hoverItem)="onHoverItem($event)"
(toggleSubMenu)="onToggleSubMenu($event)"
Expand All @@ -62,3 +67,8 @@
</li>
</ng-container>
</ul>

<ng-template #badgeTemplate>
<nb-badge [text]="badge.text" [dotMode]="badge.dotMode" [status]="badge.status">
</nb-badge>
</ng-template>
4 changes: 4 additions & 0 deletions src/framework/theme/components/menu/menu.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
}
}

.menu-item nb-badge {
position: static;
}

.menu-group span {
display: flex;
}
Expand Down
6 changes: 5 additions & 1 deletion src/framework/theme/components/menu/menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { isPlatformBrowser } from '@angular/common';
import { Router, NavigationEnd } from '@angular/router';
import { BehaviorSubject, Subject } from 'rxjs';
import { takeUntil, filter, map } from 'rxjs/operators';
import { NbMenuInternalService, NbMenuItem, NbMenuBag, NbMenuService } from './menu.service';
import { NbMenuInternalService, NbMenuItem, NbMenuBag, NbMenuService, NbMenuBadgeConfig } from './menu.service';
import { convertToBoolProperty, NbBooleanInput } from '../helpers';
import { NB_WINDOW } from '../../theme.options';
import { animate, state, style, transition, trigger } from '@angular/animations';
Expand All @@ -44,6 +44,7 @@ export enum NbToggleStates {
})
export class NbMenuItemComponent implements DoCheck, AfterViewInit, OnDestroy {
@Input() menuItem = <NbMenuItem>null;
@Input() badge: NbMenuBadgeConfig;

@Output() hoverItem = new EventEmitter<any>();
@Output() toggleSubMenu = new EventEmitter<any>();
Expand Down Expand Up @@ -156,6 +157,8 @@ export class NbMenuItemComponent implements DoCheck, AfterViewInit, OnDestroy {
* Autocollapse menu example
* @stacked-example(Autocollapse Menu, menu/menu-autocollapse.component)
*
* Menu badge
* @stacked-example(Menu item badge, menu/menu-badge.component)
*
* @styles
*
Expand Down Expand Up @@ -211,6 +214,7 @@ export class NbMenuItemComponent implements DoCheck, AfterViewInit, OnDestroy {
<ng-container *ngFor="let item of items">
<li nbMenuItem *ngIf="!item.hidden"
[menuItem]="item"
[badge]="item.badge"
[class.menu-group]="item.group"
(hoverItem)="onHoverItem($event)"
(toggleSubMenu)="onToggleSubMenu($event)"
Expand Down
7 changes: 6 additions & 1 deletion src/framework/theme/components/menu/menu.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import { NbSharedModule } from '../shared/shared.module';
import { NbMenuComponent, NbMenuItemComponent } from './menu.component';
import { NbMenuService, NbMenuInternalService } from './menu.service';
import { NbIconModule } from '../icon/icon.module';
import { NbBadgeModule } from '../badge/badge.module';

const nbMenuComponents = [NbMenuComponent, NbMenuItemComponent];

const NB_MENU_PROVIDERS = [NbMenuService, NbMenuInternalService];

@NgModule({
imports: [NbSharedModule, NbIconModule],
imports: [
NbSharedModule,
NbIconModule,
NbBadgeModule,
],
declarations: [...nbMenuComponents],
exports: [...nbMenuComponents],
})
Expand Down
8 changes: 8 additions & 0 deletions src/framework/theme/components/menu/menu.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Observable, BehaviorSubject, ReplaySubject, Subject } from 'rxjs';
import { share } from 'rxjs/operators';
import { isFragmentContain, isFragmentEqual, isUrlPathContain, isUrlPathEqual } from './url-matching-helpers';
import { NbIconConfig } from '../icon/icon.component';
import { NbBadge } from '../badge/badge.component';

export interface NbMenuBag { tag: string; item: NbMenuItem }

Expand All @@ -24,6 +25,8 @@ const itemHover$ = new ReplaySubject<NbMenuBag>(1);
const submenuToggle$ = new ReplaySubject<NbMenuBag>(1);
const collapseAll$ = new ReplaySubject<{ tag: string }>(1);

export type NbMenuBadgeConfig = Omit<NbBadge, 'position'>;

// TODO: check if we need both URL and LINK
/**
*
Expand Down Expand Up @@ -59,6 +62,11 @@ export class NbMenuItem {
* @type {boolean}
*/
expanded?: boolean;
/**
* Badge component
* @type {boolean}
*/
badge?: NbMenuBadgeConfig;
/**
* Children items
* @type {List<NbMenuItem>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
}

> .menu-items > .menu-item > a {
span, .expand-state {
span, nb-badge, .expand-state {
display: none;
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/framework/theme/components/tabset/_tabset.component.theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@
}
}

nb-badge.dot-mode.position-left {
left: nb-theme(tabset-tab–badge-dot-mode-horizontal-offset);
}

nb-badge.dot-mode.position-right {
right: nb-theme(tabset-tab–badge-dot-mode-horizontal-offset);
}

nb-badge.dot-mode.position-start {
@include nb-ltr(left, nb-theme(tabset-tab–badge-dot-mode-horizontal-offset));
@include nb-rtl(right, nb-theme(tabset-tab–badge-dot-mode-horizontal-offset));
}

nb-badge.dot-mode.position-end {
@include nb-ltr(right, nb-theme(tabset-tab–badge-dot-mode-horizontal-offset));
@include nb-rtl(left, nb-theme(tabset-tab–badge-dot-mode-horizontal-offset));
}

.tab.active {
.tab-link {
background-color: nb-theme(tabset-tab-active-background-color);
Expand Down
Loading

0 comments on commit afe02b7

Please sign in to comment.