create OpenSlides3 Material CSS Theme

Add theming options, custom component theming.
Creating themes for specfic brands is very easy now.
This commit is contained in:
Sean Engelhardt 2018-07-26 16:40:34 +02:00 committed by FinnStutzenstein
parent 76ce18cfd8
commit 41ba616dc1
10 changed files with 209 additions and 56 deletions

View File

@ -19,7 +19,7 @@
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json", "tsConfig": "src/tsconfig.app.json",
"assets": ["src/favicon.ico", "src/assets"], "assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"], "styles": ["src/styles.scss"],
"scripts": [] "scripts": []
}, },
"configurations": { "configurations": {

View File

@ -2517,11 +2517,6 @@
"integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==",
"dev": true "dev": true
}, },
"class-transformer": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.1.9.tgz",
"integrity": "sha512-KV0IteiRl95OZ9UzbuPj8RhckuHA4JTC+Q+ZbKTYPsmvB0GgPRG7JBEXiVhBq/U050OVRku4N5t0rSMHw8vDWw=="
},
"class-utils": { "class-utils": {
"version": "0.3.6", "version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@ -4629,7 +4624,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -4650,12 +4646,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -4670,17 +4668,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -4797,7 +4798,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -4809,6 +4811,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -4823,6 +4826,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -4830,12 +4834,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -4854,6 +4860,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -4934,7 +4941,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -4946,6 +4954,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -5031,7 +5040,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -5067,6 +5077,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -5086,6 +5097,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -5129,12 +5141,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -10064,7 +10078,8 @@
"reflect-metadata": { "reflect-metadata": {
"version": "0.1.12", "version": "0.1.12",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz",
"integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==" "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==",
"dev": true
}, },
"regenerate": { "regenerate": {
"version": "1.4.0", "version": "1.4.0",

View File

@ -8,7 +8,7 @@
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"e2e": "ng e2e", "e2e": "ng e2e",
"compodoc": "./node_modules/.bin/compodoc -p src/tsconfig.app.json -s -w", "compodoc": "./node_modules/.bin/compodoc --hideGenerator -p src/tsconfig.app.json -n 'OpenSlides Documentation' -d ../Compodoc -s -w -t -o",
"extract": "ngx-translate-extract -i ./src -o ./src/assets/i18n/{en,de,fr}.json --clean --sort --format-indentation ' ' --format namespaced-json", "extract": "ngx-translate-extract -i ./src -o ./src/assets/i18n/{en,de,fr}.json --clean --sort --format-indentation ' ' --format namespaced-json",
"format:fix": "pretty-quick --staged", "format:fix": "pretty-quick --staged",
"precommit": "run-s format:fix lint" "precommit": "run-s format:fix lint"

View File

@ -1,3 +1,19 @@
<p> <mat-toolbar color='primary'>
settings-list works! <span class='app-name' translate>Settings</span>
</p> </mat-toolbar>
<div *appOsPerms="['core.can_manage_config']" class="app-content">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Title
</mat-panel-title>
</mat-expansion-panel-header>
<p> CONTENT </p>
</mat-expansion-panel>
</mat-accordion>
</div>

View File

@ -1,6 +1,6 @@
<mat-sidenav-container autosize> <mat-sidenav-container autosize>
<mat-sidenav #sideNav [mode]="isMobile ? 'push' : 'side'" [opened]='!isMobile' disableClose='!isMobile'> <mat-sidenav #sideNav [mode]="isMobile ? 'push' : 'side'" [opened]='!isMobile' disableClose='!isMobile'>
<mat-toolbar class='nav-toolbar' color='primary'> <mat-toolbar class='nav-toolbar'>
<!-- logo --> <!-- logo -->
<mat-toolbar-row> <mat-toolbar-row>
@ -9,7 +9,7 @@
</mat-toolbar> </mat-toolbar>
<!-- User Menu --> <!-- User Menu -->
<mat-expansion-panel> <mat-expansion-panel class='user-menu mat-elevation-z0'>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<!-- Get the username from operator --> <!-- Get the username from operator -->
{{username}} {{username}}
@ -20,35 +20,56 @@
</mat-expansion-panel> </mat-expansion-panel>
<!-- navigation --> <!-- navigation -->
<mat-nav-list> <mat-nav-list class='main-nav'>
<a *appOsPerms="['core.can_see_frontpage']" mat-list-item routerLink='/' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['core.can_see_frontpage']" mat-list-item routerLink='/' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='home'></fa-icon> <fa-icon icon='home'></fa-icon>
<span translate>Home</span> <span translate>Home</span>
</a> </a>
<a *appOsPerms="['agenda.can_see']" mat-list-item routerLink='/agenda' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['agenda.can_see']" mat-list-item routerLink='/agenda' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='calendar'></fa-icon> <fa-icon icon='calendar'></fa-icon>
<span translate>Agenda</span> <span translate>Agenda</span>
</a> </a>
<a *appOsPerms="['motions.can_see']" mat-list-item routerLink='/motions' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['motions.can_see']" mat-list-item routerLink='/motions' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='file-alt'></fa-icon> <fa-icon icon='file-alt'></fa-icon>
<span translate>Motions</span> <span translate>Motions</span>
</a> </a>
<a *appOsPerms="['assignments.can_see']" mat-list-item routerLink='/assignments' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['assignments.can_see']" mat-list-item routerLink='/assignments' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='chart-pie'></fa-icon> <fa-icon icon='chart-pie'></fa-icon>
<span translate>Assignments</span> <span translate>Assignments</span>
</a> </a>
<a *appOsPerms="['users.can_see_name']" mat-list-item routerLink='/users' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['users.can_see_name']" mat-list-item routerLink='/users' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='user'></fa-icon> <fa-icon icon='user'></fa-icon>
<span translate>Participants</span> <span translate>Participants</span>
</a> </a>
<a *appOsPerms="['mediafiles.can_see']" mat-list-item routerLink='/mediafiles' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['mediafiles.can_see']" mat-list-item routerLink='/mediafiles' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='paperclip'></fa-icon> <fa-icon icon='paperclip'></fa-icon>
<span translate>Files</span> <span translate>Files</span>
</a> </a>
<a *appOsPerms="['core.can_manage_config']" mat-list-item routerLink='/settings' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'> <a *appOsPerms="['core.can_manage_config']" mat-list-item routerLink='/settings' routerLinkActive='active' (click)='isMobile ? sideNav.toggle() : null'>
<fa-icon icon='cog'></fa-icon> <fa-icon icon='cog'></fa-icon>
<span translate>Settings</span> <span translate>Settings</span>
</a> </a>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>

View File

@ -0,0 +1,42 @@
@import '~@angular/material/theming';
/** Custom component theme. Only lives in a specific scope */
@mixin app-site-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, accent);
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
app-site {
/** change the nav-toolbar to the darker nuance of the current theme*/
.nav-toolbar {
background-color: mat-color($primary, darker);
}
/** make the .user-menu expansion panel look like the nav-toolbar above */
.user-menu {
background-color: mat-color($primary, darker);
color: mat-color($primary, default-contrast);
min-height: 64px;
.mat-expansion-indicator:after {
color: mat-color($primary, default-contrast);
}
}
/** style and allign the nav icons the icons*/
.main-nav {
.ng-fa-icon {
color: mat-color($primary, lighter-contrast);
min-width: 20px; //puts the text to the right on the same leve
margin-right: 10px; // the distance from the icon to the text
}
span {
color: mat-color($primary, lighter-contrast);
}
// color: mat-color($primary, default-contrast);
}
}
}

View File

@ -12,7 +12,7 @@ import { BaseComponent } from 'app/base.component';
@Component({ @Component({
selector: 'app-site', selector: 'app-site',
templateUrl: './site.component.html', templateUrl: './site.component.html',
styleUrls: ['./site.component.css'] styleUrls: ['./site.component.scss']
}) })
export class SiteComponent extends BaseComponent implements OnInit { export class SiteComponent extends BaseComponent implements OnInit {
username = this.operator.username; username = this.operator.username;

View File

@ -0,0 +1,42 @@
// define a real custom palette (using http://mcg.mbitson.com)
$openslides-blue: (
50: #e6eff2,
100: #c1d6e0,
200: #98bbcb,
300: #6fa0b6,
400: #508ba6,
500: #317796,
600: #2c6f8e,
700: #002a42,
800: #00253c,
900: #001f33,
A100: #9fd7ff,
A200: #6cc2ff,
A400: #39acff,
A700: #1fa2ff,
contrast: (
50: #ebebeb,
100: #535353,
200: #ebebeb,
300: #ebebeb,
400: #fefefe,
500: #fefefe,
600: #fefefe,
700: #fefefe,
800: #fefefe,
900: #fefefe,
A100: #000000,
A200: #000000,
A400: #000000,
A700: #000000
)
);
// Generate paletes using: https://material.io/design/color/
// default values fir mat-palette: $default: 500, $lighter: 100, $darker: 700.
$openslides-primary: mat-palette($openslides-blue);
$openslides-accent: mat-palette($mat-pink, A200, A100, A400);
$openslides-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$openslides-theme: mat-light-theme($openslides-primary, $openslides-accent, $openslides-warn);

View File

@ -1,5 +1,22 @@
/*use a 'theme' for MaterialUI. TODO We will need to build an OpenSlides-Theme*/ @import '~@angular/material/theming';
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
@include mat-core();
/** Import brand theme and (new) component themes */
@import './assets/styles/openslides-theme';
@import './app/site/site.component.scss-theme';
@mixin openslides-components-theme($theme) {
@include app-site-theme($theme);
/** More components are added here */
}
@include angular-material-theme($openslides-theme);
@include openslides-components-theme($openslides-theme);
* {
font-family: Arial, Helvetica, sans-serif !important;
}
html, html,
body { body {