Implement ripple effect for material themes

This commit is contained in:
eugene-sinitsyn 2020-03-04 19:31:08 +03:00
parent b03633ba9f
commit 690bd322c2
12 changed files with 70 additions and 19 deletions

20
package-lock.json generated
View file

@ -363,18 +363,17 @@
"integrity": "sha512-zTCgrIAA9FYPMbqqpQnoNltiLR58q0FMfzP2t96q/1tjyVy/Y/IaNgVQ7eL0HeQ0nG6IAzQ1HVx8Xeneg4Yj5Q==" "integrity": "sha512-zTCgrIAA9FYPMbqqpQnoNltiLR58q0FMfzP2t96q/1tjyVy/Y/IaNgVQ7eL0HeQ0nG6IAzQ1HVx8Xeneg4Yj5Q=="
}, },
"@angular/cdk": { "@angular/cdk": {
"version": "8.0.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.0.0.tgz", "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-9.1.0.tgz",
"integrity": "sha512-2vsRWEHNARe0iRmqgzvM67gwfRy+aKvdef4Qu9L+ndSsTrrZT3tSgG8SMn1v9SfBHnx5G8mo4d1AMquXG69AuQ==", "integrity": "sha512-qKpAudJx9z0MD+ADptS0OZViJBTA49+JCKym0hPQUkcB9Po4Al6gu6oZ1VSXV5Ln3T84z9aAw/AhUGP/YCFNSQ==",
"requires": { "requires": {
"parse5": "^5.0.0", "parse5": "^5.0.0"
"tslib": "^1.7.1"
}, },
"dependencies": { "dependencies": {
"parse5": { "parse5": {
"version": "5.1.0", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
"optional": true "optional": true
} }
} }
@ -857,6 +856,11 @@
"integrity": "sha512-Q/kFQV4mjZ/Mpx6GksriM5lingjX73EwtVc79AfVMA76Pv5XqfYQZuti6tk7DvYQD89sv1Z/iN2di+ZLKsSTnw==", "integrity": "sha512-Q/kFQV4mjZ/Mpx6GksriM5lingjX73EwtVc79AfVMA76Pv5XqfYQZuti6tk7DvYQD89sv1Z/iN2di+ZLKsSTnw==",
"dev": true "dev": true
}, },
"@angular/material": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-9.1.0.tgz",
"integrity": "sha512-KjA1ARoZ1vBg4jUH1y39muynxAFvkD8QZFGKH8Nh4zXW5pOP/7NyjokxXsNx5qSBCq/6ac2xBxCrCYJN7HmoDw=="
},
"@angular/platform-browser": { "@angular/platform-browser": {
"version": "9.0.4", "version": "9.0.4",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.0.4.tgz", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.0.4.tgz",

View file

@ -31,12 +31,13 @@
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^9.0.4", "@angular/animations": "^9.0.4",
"@angular/cdk": "^8.0.0", "@angular/cdk": "^9.1.0",
"@angular/common": "^9.0.4", "@angular/common": "^9.0.4",
"@angular/compiler": "^9.0.4", "@angular/compiler": "^9.0.4",
"@angular/core": "^9.0.4", "@angular/core": "^9.0.4",
"@angular/forms": "^9.0.4", "@angular/forms": "^9.0.4",
"@angular/google-maps": "^9.1.0", "@angular/google-maps": "^9.1.0",
"@angular/material": "^9.1.0",
"@angular/platform-browser": "^9.0.4", "@angular/platform-browser": "^9.0.4",
"@angular/platform-browser-dynamic": "^9.0.4", "@angular/platform-browser-dynamic": "^9.0.4",
"@angular/router": "^9.0.4", "@angular/router": "^9.0.4",

View file

@ -1,5 +1,6 @@
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MAT_RIPPLE_GLOBAL_OPTIONS } from '@angular/material/core';
import { NbAuthModule, NbDummyAuthStrategy } from '@nebular/auth'; import { NbAuthModule, NbDummyAuthStrategy } from '@nebular/auth';
import { NbSecurityModule, NbRoleProvider } from '@nebular/security'; import { NbSecurityModule, NbRoleProvider } from '@nebular/security';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
@ -51,6 +52,7 @@ import { CountryOrderService } from './mock/country-order.service';
import { StatsProgressBarService } from './mock/stats-progress-bar.service'; import { StatsProgressBarService } from './mock/stats-progress-bar.service';
import { VisitorsAnalyticsService } from './mock/visitors-analytics.service'; import { VisitorsAnalyticsService } from './mock/visitors-analytics.service';
import { SecurityCamerasService } from './mock/security-cameras.service'; import { SecurityCamerasService } from './mock/security-cameras.service';
import { RippleService } from './utils/ripple.service';
import { MockDataModule } from './mock/mock-data.module'; import { MockDataModule } from './mock/mock-data.module';
const socialLinks = [ const socialLinks = [
@ -91,6 +93,7 @@ const DATA_SERVICES = [
{ provide: StatsProgressBarData, useClass: StatsProgressBarService }, { provide: StatsProgressBarData, useClass: StatsProgressBarService },
{ provide: VisitorsAnalyticsData, useClass: VisitorsAnalyticsService }, { provide: VisitorsAnalyticsData, useClass: VisitorsAnalyticsService },
{ provide: SecurityCamerasData, useClass: SecurityCamerasService }, { provide: SecurityCamerasData, useClass: SecurityCamerasService },
{provide: MAT_RIPPLE_GLOBAL_OPTIONS, useExisting: RippleService},
]; ];
export class NbSimpleRoleProvider extends NbRoleProvider { export class NbSimpleRoleProvider extends NbRoleProvider {

View file

@ -0,0 +1,11 @@
import { Injectable } from '@angular/core';
import { RippleGlobalOptions } from '@angular/material/core';
@Injectable({providedIn: 'root'})
export class RippleService implements RippleGlobalOptions {
public disabled: boolean = false;
public toggle(enabled: boolean): void {
this.disabled = !enabled;
}
}

View file

@ -5,6 +5,7 @@ import { UserData } from '../../../@core/data/users';
import { LayoutService } from '../../../@core/utils'; import { LayoutService } from '../../../@core/utils';
import { map, takeUntil } from 'rxjs/operators'; import { map, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { RippleService } from '../../../@core/utils/ripple.service';
@Component({ @Component({
selector: 'ngx-header', selector: 'ngx-header',
@ -53,7 +54,8 @@ export class HeaderComponent implements OnInit, OnDestroy {
private themeService: NbThemeService, private themeService: NbThemeService,
private userService: UserData, private userService: UserData,
private layoutService: LayoutService, private layoutService: LayoutService,
private breakpointService: NbMediaBreakpointsService) { private breakpointService: NbMediaBreakpointsService,
private rippleService: RippleService) {
} }
ngOnInit() { ngOnInit() {
@ -76,7 +78,10 @@ export class HeaderComponent implements OnInit, OnDestroy {
map(({ name }) => name), map(({ name }) => name),
takeUntil(this.destroy$), takeUntil(this.destroy$),
) )
.subscribe(themeName => this.currentTheme = themeName); .subscribe(themeName => {
this.currentTheme = themeName;
this.rippleService.toggle(themeName?.startsWith('material'));
});
} }
ngOnDestroy() { ngOnDestroy() {

View file

@ -0,0 +1,21 @@
@mixin ngx-ripple() {
.mat-ripple {
overflow: hidden;
position: relative;
&:not(:empty) {
transform: translateZ(0);
}
}
.mat-ripple-element {
position: absolute;
border-radius: 50%;
pointer-events: none;
transition: opacity, transform 0ms cubic-bezier(0, 0, 0.2, 1);
transform: scale(0);
// switch ripple color depending on selected theme
background-color: nb-theme(background-alternative-color-4);
opacity: .1;
}
}

View file

@ -18,6 +18,7 @@
@import './layout'; @import './layout';
@import './overrides'; @import './overrides';
@import './ripple';
// install the framework and custom global styles // install the framework and custom global styles
@include nb-install() { @include nb-install() {
@ -31,4 +32,5 @@
@include ngx-pace-theme(); @include ngx-pace-theme();
@include nb-overrides(); @include nb-overrides();
@include ngx-ripple();
}; };

View file

@ -1,5 +1,6 @@
import { ModuleWithProviders, NgModule } from '@angular/core'; import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { MatRippleModule } from '@angular/material/core';
import { import {
NbActionsModule, NbActionsModule,
NbLayoutModule, NbLayoutModule,
@ -73,8 +74,8 @@ const PIPES = [
]; ];
@NgModule({ @NgModule({
imports: [CommonModule, ...NB_MODULES], imports: [CommonModule, MatRippleModule, ...NB_MODULES],
exports: [CommonModule, ...PIPES, ...COMPONENTS], exports: [CommonModule, MatRippleModule, ...PIPES, ...COMPONENTS],
declarations: [...COMPONENTS, ...PIPES], declarations: [...COMPONENTS, ...PIPES],
}) })
export class ThemeModule { export class ThemeModule {

View file

@ -54,6 +54,8 @@ export class DashboardComponent implements OnDestroy {
cosmic: CardSettings[]; cosmic: CardSettings[];
corporate: CardSettings[]; corporate: CardSettings[];
dark: CardSettings[]; dark: CardSettings[];
'material-dark': CardSettings[];
'material-light': CardSettings[];
} = { } = {
default: this.commonStatusCardsSet, default: this.commonStatusCardsSet,
cosmic: this.commonStatusCardsSet, cosmic: this.commonStatusCardsSet,
@ -76,6 +78,8 @@ export class DashboardComponent implements OnDestroy {
}, },
], ],
dark: this.commonStatusCardsSet, dark: this.commonStatusCardsSet,
'material-dark': this.commonStatusCardsSet,
'material-light': this.commonStatusCardsSet,
}; };
constructor(private themeService: NbThemeService, constructor(private themeService: NbThemeService,

View file

@ -5,7 +5,6 @@
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
height: 6rem; height: 6rem;
overflow: visible;
.icon-container { .icon-container {
height: 100%; height: 100%;

View file

@ -4,7 +4,7 @@ import { Component, Input } from '@angular/core';
selector: 'ngx-status-card', selector: 'ngx-status-card',
styleUrls: ['./status-card.component.scss'], styleUrls: ['./status-card.component.scss'],
template: ` template: `
<nb-card (click)="on = !on" [ngClass]="{'off': !on}"> <nb-card matRipple (click)="on = !on" [ngClass]="{'off': !on}">
<div class="icon-container"> <div class="icon-container">
<div class="icon status-{{ type }}"> <div class="icon status-{{ type }}">
<ng-content></ng-content> <ng-content></ng-content>

View file

@ -20,16 +20,16 @@
</div> </div>
<nb-radio-group [(ngModel)]="temperatureMode" name="temperature-mode"> <nb-radio-group [(ngModel)]="temperatureMode" name="temperature-mode">
<nb-radio value="cool"> <nb-radio matRipple value="cool">
<i class="nb-snowy-circled"></i> <i class="nb-snowy-circled"></i>
</nb-radio> </nb-radio>
<nb-radio value="warm"> <nb-radio matRipple value="warm">
<i class="nb-sunny-circled"></i> <i class="nb-sunny-circled"></i>
</nb-radio> </nb-radio>
<nb-radio value="heat"> <nb-radio matRipple value="heat">
<i class="nb-flame-circled"></i> <i class="nb-flame-circled"></i>
</nb-radio> </nb-radio>
<nb-radio value="fan"> <nb-radio matRipple value="fan">
<i class="nb-loop-circled"></i> <i class="nb-loop-circled"></i>
</nb-radio> </nb-radio>
</nb-radio-group> </nb-radio-group>