Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a dark mode #4017

Merged
merged 15 commits into from
Dec 4, 2019
20 changes: 19 additions & 1 deletion docs/customizing.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ In this file you can set any or all of the following variables:
|---|---|
|$stratos-theme|The main theme to use for Stratos|
|$stratos-nav-theme|Theme to use for the side navigation panel|
$stratos-status-theme|Theme to use for displaying status in Stratos|
|$stratos-status-theme|Theme to use for displaying status in Stratos|

Note that you do not have to specify all of these - defaults will be used if they are not set.

Expand All @@ -72,6 +72,24 @@ $suse-app-theme: mat-light-theme($suse-app-primary, $suse-app-primary, $suse-the
$stratos-theme: $suse-app-theme;
```

#### Creating or disabling the Dark theme

You can also change the Dark theme, if you wish, by defining the following variables:

|Variable|Purpose|
|---|---|
|$stratos-dark-theme|The dark theme to use for Stratos|
|$stratos-dark-nav-theme|Dark theme to use for the side navigation panel|
|$stratos-dark-status-theme|Dark theme to use for displaying status in Stratos|

Note that minimally you must supply `stratos-dark-theme` to create a dark theme.

By default a dark theme is assumed to be available and the default will be used if not overridden. You can disable dark theme support in the UI by setting the following variable in your `custom.scss`:

```
$stratos-dark-theme-supported: false;
```

### Changing Styles

We don't generally recommend modifying styles, since from version to version of Stratos, we may change the styles used slightly which can mean any modifications you made will need updating. Should you wish to do so, you can modify these in the same `custom.scss` file that is used for theming.
Expand Down
8 changes: 7 additions & 1 deletion examples/custom-src/frontend/sass/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

// ACME Primary Material Design pallette
// From http://mcg.mbitson.com/#!?mcgpalette0=%233f51b5
$acme-primary: (50: #e0f7f0, 100: #b3ecd9, 200: #80e0c0, 300: #4dd3a7, 400: #26c994, 500: #00c081, 600: #00ba79, 700: #00b26e, 800: #00aa64, 900: #009c51, A100: #c7ffe0, A200: #94ffc4, A400: #61ffa8, A700: #47ff9a, contrast: (50: #000, 100: #000, 200: #000, 300: #000, 400: #000, 500: #fff, 600: #fff, 700: #fff, 800: #fff, 900: #fff, A100: #000, A200: #000, A400: #000, A700: #000));
$acme-primary: (50: #e8eaf6, 100: #c5cbe9, 200: #9fa8da, 300: #7985cb, 400: #5c6bc0, 500: #3f51b5, 600: #394aae, 700: #3140a5, 800: #29379d, 900: #1b278d, A100: #c6cbff, A200: #939dff, A400: #606eff, A700: #4757ff, contrast: ( 50: #000000, 100: #000000, 200: #000000, 300: #000000, 400: #ffffff, 500: #ffffff, 600: #ffffff, 700: #ffffff, 800: #ffffff, 900: #ffffff, A100: #000000, A200: #000000, A400: #ffffff, A700: #ffffff, ));
$mat-red: ( 50: #ffebee, 100: #ffcdd2, 200: #ef9a9a, 300: #e57373, 400: #ef5350, 500: #f44336, 600: #e53935, 700: #d32f2f, 800: #c62828, 900: #b71c1c, A100: #ff8a80, A200: #ff5252, A400: #ff1744, A700: #d50000, contrast: ( 50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: $black-87-opacity, 400: $black-87-opacity, 500: white, 600: white, 700: white, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: white, ));

// Common
$acme-theme-primary: mat-palette($acme-primary);
$acme-theme-warn: mat-palette($mat-red);

// Dark Theme
$stratos-dark-theme: mat-dark-theme($acme-theme-primary, $acme-theme-primary, $acme-theme-warn);

// Default Theme
$stratos-theme: mat-light-theme($acme-theme-primary, $acme-theme-primary, $acme-theme-warn);

@import 'custom/acme';
2 changes: 1 addition & 1 deletion examples/custom-src/frontend/sass/custom/acme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ $acme-blue: #073155;
$acme-side-nav: $acme-secondary;
$acme-side-nav-active: #003358;

.stratos {
body.stratos {
app-page-subheader {
.page-subheader {
background-color: #fff;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"ng": "ng",
"start": "npm run customize && ng serve",
"start-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve",
"start-dev-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --aot=false",
"start-prod-high-mem": "npm run customize && node --max_old_space_size=8192 node_modules/@angular/cli/bin/ng serve --prod",
"start-dev": "ng serve --aot=false",
"test": "run-s test-frontend:* --continue-on-error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mat-card-header {
.autoscaler-metric-subtitle {
color: rgba(0, 0, 0, .54);
font-size: .9em;
margin-top: .3em;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { GitAppDetails, OverrideAppDetails, SourceType } from '../store/types/de
import { GitBranch, GitCommit } from '../store/types/git.types';

export const SET_APP_SOURCE_DETAILS = '[Deploy App] Application Source';
export const CHECK_PROJECT_EXISTS = '[Deploy App] Check Projet exists';
export const CHECK_PROJECT_EXISTS = '[Deploy App] Check Project exists';
export const PROJECT_DOESNT_EXIST = '[Deploy App] Project Doesn\'t exist';
export const PROJECT_FETCH_FAILED = '[Deploy App] Project Fetch Failed';
export const PROJECT_EXISTS = '[Deploy App] Project exists';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
@import '~@angular/material/theming';
@mixin app-deploy-app-theme($theme, $app-theme) {
$is-dark: map-get($theme, is-dark);

$ansi-colors: map-get($app-theme, ansi-colors);
$background-color: map-get(map-get($ansi-colors, 'white'), intense);

@if $is-dark == true {
$background-colors: map-get($theme, background);
$foreground-colors: map-get($theme, foreground);
$background-color: lighten(mat-color($background-colors, background), 5%);
}

.deploy-app {
background-color: map-get(map-get($ansi-colors, 'white'), intense);
background-color: $background-color;
}
}
1 change: 0 additions & 1 deletion src/frontend/packages/core/misc/custom/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
// This file is in the .gitignore - changes will not be flagged

// The customization build step will replace this file with the custom one if provided

24 changes: 11 additions & 13 deletions src/frontend/packages/core/sass/_all-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
@import '../src/shared/components/app-action-monitor-icon/app-action-monitor-icon.component.theme';
@import '../src/shared/components/upload-progress-indicator/upload-progress-indicator.component.theme';
@import '../src/shared/components/list/list-cards/meta-card/meta-card-base/meta-card.component.theme';
@import '../src/shared/components/list/list-cards/meta-card/meta-card-item/meta-card-item.component.theme';
@import '../src/shared/components/start-end-date/start-end-date.component.theme';
@import '../src/shared/components/metrics-chart/metrics-chart.component.theme';
@import '../src/shared/components/metrics-range-selector/metrics-range-selector.component.theme';
Expand All @@ -41,7 +42,8 @@
@import '../src/features/user-profile/profile-info/profile-info.component.theme';
@import '../src/core/stateful-icon/stateful-icon.component.theme';
@import '../src/shared/components/markdown-preview/markdown-preview.component.theme';
@import './components/mat-tabs.theme';
@import './components/mat-snack-bar.theme';
@import './components/ngx-charts-gauge.theme';
@import './components/text-status.theme';
@import './components/hyperlinks.theme';
@import './mat-themes';
Expand Down Expand Up @@ -82,12 +84,10 @@ $side-nav-light-active: #484848;
$warn: map-get($theme, warn);
$subdued: mat-contrast($primary, 50);

@if $is-dark==true {
@if $is-dark == true {
$app-background-color: lighten(mat-color($background-colors, background), 10%);
$subdued: darken($subdued, 50);
}

@else {
$subdued: lighten($subdued, 90);
} @else {
$app-background-color: darken(mat-color($background-colors, background), 2%);
$subdued: lighten($subdued, 50);
}
Expand All @@ -106,7 +106,8 @@ $side-nav-light-active: #484848;
@include steppers-theme($theme, $app-theme);
@include list-theme($theme, $app-theme);
@include app-base-page-theme($theme, $app-theme);
@include app-mat-tabs-theme($theme, $app-theme);
@include app-mat-snack-bar-theme($theme, $app-theme);
@include ngx-charts-gauge($theme, $app-theme);
@include app-text-status-theme($theme, $app-theme);
@include app-card-status-theme($theme, $app-theme);
@include app-usage-gauge-theme($theme, $app-theme);
Expand Down Expand Up @@ -149,15 +150,14 @@ $side-nav-light-active: #484848;
@include page-side-nav-theme($theme, $app-theme);
@include cf-admin-add-user-warning($theme, $app-theme);
@include entity-summary-title-theme($theme, $app-theme);
@include app-meta-card-item-theme($theme, $app-theme);
@include error-page-theme($theme, $app-theme);
}

@function app-generate-nav-theme($theme, $nav-theme: null) {
@if ($nav-theme) {
@return $nav-theme;
}

@else {
} @else {
// Use default palette for side navigation
@return (background: $side-nav-light-bg, background-top: $side-nav-light-bg, text: darken($side-nav-light-text, 10%), active: $side-nav-light-active, active-text: $side-nav-light-text, hover: $side-nav-light-hover, hover-text: $side-nav-light-text);
}
Expand All @@ -166,9 +166,7 @@ $side-nav-light-active: #484848;
@function app-generate-status-theme($theme, $status-theme: null) {
@if ($status-theme) {
@return $status-theme;
}

@else {
} @else {
$warn: map-get($theme, warn);
$primary: map-get($theme, primary);
$white: #fff; // Use default palette for status
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@mixin app-mat-snack-bar-theme($theme, $app-theme) {
$is-dark: map-get($theme, is-dark);
$background-colors: map-get($theme, background);
$foreground-colors: map-get($theme, foreground);

$background-color: mat-color($foreground-colors, text);
$color: mat-color($background-colors, text);

@if $is-dark == true {
$background-color: lighten(mat-color($background-colors, background), 5%);
$color: mat-color($foreground-colors, text);
}

.mat-snack-bar-container {
background-color: $background-color;
.mat-simple-snackbar {
color: $color;
}
}
}
20 changes: 0 additions & 20 deletions src/frontend/packages/core/sass/components/mat-tabs.theme.scss

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@mixin ngx-charts-gauge($theme, $app-theme) {
$foreground-colors: map-get($theme, foreground);
ngx-charts-chart text {
fill: mat-color($foreground-colors, text);
}
}
44 changes: 32 additions & 12 deletions src/frontend/packages/core/sass/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,38 @@
// Custom theme support
@import './custom';

// Themes palettes and colors
$oss-theme-primary: mat-palette($mat-blue);
$oss-theme-accent: mat-palette($mat-blue);
$oss-theme-warn: mat-palette($mat-red);
$oss-theme: mat-light-theme($oss-theme-primary, $oss-theme-accent, $oss-theme-warn);
.dark-theme {
// Dark Theme defaults
$dark-primary: mat-palette($mat-blue);
$dark-accent: mat-palette($mat-amber, A400, A100, A700);
$dark-warn: mat-palette($mat-red);
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

// Default to using the open source theme
$stratos-theme: $oss-theme !default;
$stratos-nav-theme: null !default;
$stratos-status-theme: null !default;
$stratos-dark-theme: $dark-theme !default;
$stratos-dark-nav-theme: null !default;
$stratos-dark-status-theme: null !default;

@include angular-material-theme($stratos-dark-theme);
@include app-theme($stratos-dark-theme, $stratos-dark-nav-theme, $stratos-dark-status-theme);
}

.default {
// Themes palettes and colors
$oss-theme-primary: mat-palette($mat-blue);
$oss-theme-accent: mat-palette($mat-blue);
$oss-theme-warn: mat-palette($mat-red);
$oss-theme: mat-light-theme($oss-theme-primary, $oss-theme-accent, $oss-theme-warn);

// Default to using the open source theme
$stratos-theme: $oss-theme !default;
$stratos-nav-theme: null !default;
$stratos-status-theme: null !default;

@include angular-material-theme($stratos-theme);
@include app-theme($stratos-theme, $stratos-nav-theme, $stratos-status-theme);
}

$stratos-dark-theme-supported: true !default;

// Create the theme
@include mat-core();
@include angular-material-theme($stratos-theme);
@include app-theme($stratos-theme, $stratos-nav-theme, $stratos-status-theme);
@include mat-core;
7 changes: 5 additions & 2 deletions src/frontend/packages/core/src/app.component.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
<router-outlet></router-outlet>
<div class="user-id" *ngIf="userId$ | async as userId" id="__stratos-userid__">{{userId}}</div>
<span [ngClass]="(themeService.getTheme() | async).styleName">

<router-outlet></router-outlet>
<div class="user-id" *ngIf="userId$ | async as userId" id="__stratos-userid__">{{userId}}</div>
</span>
4 changes: 3 additions & 1 deletion src/frontend/packages/core/src/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Observable } from 'rxjs';
import { create } from 'rxjs-spy';

import { AuthOnlyAppState } from '../../store/src/app-state';
import { ThemeService } from './core/theme.service';
import { environment } from './environments/environment';
import { LoggedInService } from './logged-in.service';

Expand All @@ -20,7 +21,8 @@ export class AppComponent implements OnInit, OnDestroy, AfterContentInit {

constructor(
private loggedInService: LoggedInService,
store: Store<AuthOnlyAppState>
store: Store<AuthOnlyAppState>,
public themeService: ThemeService
) {
// We use the username to key the session storage. We could replace this with the users id?
this.userId$ = store.select(state => state.auth.sessionData && state.auth.sessionData.user ? state.auth.sessionData.user.name : null);
Expand Down
38 changes: 38 additions & 0 deletions src/frontend/packages/core/src/core/style.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root',
})
export class StyleService {

private rules: string[] = [];
constructor() {
this.rules = this.getAllSelectors();
}

hasSelector = (selector) => {
return !!this.rules.find(ruleSelector => ruleSelector === selector);
}

private getAllSelectors = (): string[] => {
const ret = [];
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < document.styleSheets.length; i++) {
const styleSheet = document.styleSheets[i];
if (!(styleSheet instanceof CSSStyleSheet)) {
continue;
}
const rules = styleSheet.rules || styleSheet.cssRules;
// tslint:disable-next-line:prefer-for-of
for (let y = 0; y < rules.length; y++) {
const rule = rules[y];
if (!(rule instanceof CSSStyleRule)) {
continue;
}
if (typeof rule.selectorText === 'string') { ret.push(rule.selectorText); }
}
}
return ret;
}

}
Loading