diff --git a/gulpfile.babel.js b/gulpfile.babel.js
index ad8adda2e..cea42d6c9 100644
--- a/gulpfile.babel.js
+++ b/gulpfile.babel.js
@@ -7,11 +7,20 @@ import { exec } from 'child_process';
import dotenv from 'dotenv';
import sassVariables from 'gulp-sass-variables';
import { removeSync } from 'fs-extra';
+import kebabCase from 'kebab-case';
+import hexRgb from 'hex-rgb';
import config from './package.json';
+import * as rawStyleConfig from './src/theme/default/legacy.js';
+
dotenv.config();
+const styleConfig = Object.keys(rawStyleConfig).map((key) => {
+ const isHex = /^#[0-9A-F]{6}$/i.test(rawStyleConfig[key]);
+ return ({ [`$raw_${kebabCase(key)}`]: isHex ? hexRgb(rawStyleConfig[key], { format: 'array' }).splice(0, 3).join(',') : rawStyleConfig[key] });
+});
+
const paths = {
src: 'src',
dest: 'build',
@@ -83,9 +92,9 @@ export function html() {
export function styles() {
return gulp.src(paths.styles.src)
- .pipe(sassVariables({
+ .pipe(sassVariables(Object.assign({
$env: process.env.NODE_ENV === 'development' ? 'development' : 'production',
- }))
+ }, ...styleConfig)))
.pipe(sass({
includePaths: [
'./node_modules',
diff --git a/package-lock.json b/package-lock.json
index 1dcd57e01..6f1f11eba 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2006,6 +2006,11 @@
}
}
},
+ "brcast": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.1.tgz",
+ "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg=="
+ },
"browserslist": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.2.tgz",
@@ -3010,6 +3015,14 @@
"integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=",
"dev": true
},
+ "css-vendor": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz",
+ "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=",
+ "requires": {
+ "is-in-browser": "^1.0.2"
+ }
+ },
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -6745,6 +6758,12 @@
"resolved": "https://registry.npmjs.org/hashids/-/hashids-1.2.2.tgz",
"integrity": "sha512-dEHCG2LraR6PNvSGxosZHIRgxF5sNLOIBFEHbj8lfP9WWmu/PWPMzsip1drdVSOFi51N2pU7gZavrgn7sbGFuw=="
},
+ "hex-rgb": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-3.0.0.tgz",
+ "integrity": "sha512-iWOUTZu7KQGhErV8JfTQDH5F/M2D0HVd0sexS4Grg4e4RYAiN3c4jfpPqKgfedqeebKcNZBl2z3zlgCtFjpFJQ==",
+ "dev": true
+ },
"history": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/history/-/history-3.3.0.tgz",
@@ -6967,6 +6986,11 @@
}
}
},
+ "hyphenate-style-name": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
+ "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
+ },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -7352,6 +7376,11 @@
"number-is-nan": "^1.0.0"
}
},
+ "is-function": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz",
+ "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU="
+ },
"is-glob": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
@@ -7361,6 +7390,11 @@
"is-extglob": "^2.1.1"
}
},
+ "is-in-browser": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
+ "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
+ },
"is-installed-globally": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
@@ -7727,6 +7761,108 @@
"verror": "1.10.0"
}
},
+ "jss": {
+ "version": "9.8.7",
+ "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz",
+ "integrity": "sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ==",
+ "requires": {
+ "is-in-browser": "^1.1.3",
+ "symbol-observable": "^1.1.0",
+ "warning": "^3.0.0"
+ },
+ "dependencies": {
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+ }
+ }
+ },
+ "jss-camel-case": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz",
+ "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==",
+ "requires": {
+ "hyphenate-style-name": "^1.0.2"
+ }
+ },
+ "jss-compose": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/jss-compose/-/jss-compose-5.0.0.tgz",
+ "integrity": "sha512-YofRYuiA0+VbeOw0VjgkyO380sA4+TWDrW52nSluD9n+1FWOlDzNbgpZ/Sb3Y46+DcAbOS21W5jo6SAqUEiuwA==",
+ "requires": {
+ "warning": "^3.0.0"
+ }
+ },
+ "jss-default-unit": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/jss-default-unit/-/jss-default-unit-8.0.2.tgz",
+ "integrity": "sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg=="
+ },
+ "jss-expand": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/jss-expand/-/jss-expand-5.3.0.tgz",
+ "integrity": "sha512-NiM4TbDVE0ykXSAw6dfFmB1LIqXP/jdd0ZMnlvlGgEMkMt+weJIl8Ynq1DsuBY9WwkNyzWktdqcEW2VN0RAtQg=="
+ },
+ "jss-extend": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/jss-extend/-/jss-extend-6.2.0.tgz",
+ "integrity": "sha512-YszrmcB6o9HOsKPszK7NeDBNNjVyiW864jfoiHoMlgMIg2qlxKw70axZHqgczXHDcoyi/0/ikP1XaHDPRvYtEA==",
+ "requires": {
+ "warning": "^3.0.0"
+ }
+ },
+ "jss-global": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/jss-global/-/jss-global-3.0.0.tgz",
+ "integrity": "sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q=="
+ },
+ "jss-nested": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz",
+ "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==",
+ "requires": {
+ "warning": "^3.0.0"
+ }
+ },
+ "jss-preset-default": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.5.0.tgz",
+ "integrity": "sha512-qZbpRVtHT7hBPpZEBPFfafZKWmq3tA/An5RNqywDsZQGrlinIF/mGD9lmj6jGqu8GrED2SMHZ3pPKLmjCZoiaQ==",
+ "requires": {
+ "jss-camel-case": "^6.1.0",
+ "jss-compose": "^5.0.0",
+ "jss-default-unit": "^8.0.2",
+ "jss-expand": "^5.3.0",
+ "jss-extend": "^6.2.0",
+ "jss-global": "^3.0.0",
+ "jss-nested": "^6.0.1",
+ "jss-props-sort": "^6.0.0",
+ "jss-template": "^1.0.1",
+ "jss-vendor-prefixer": "^7.0.0"
+ }
+ },
+ "jss-props-sort": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz",
+ "integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g=="
+ },
+ "jss-template": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.1.tgz",
+ "integrity": "sha512-m5BqEWha17fmIVXm1z8xbJhY6GFJxNB9H68GVnCWPyGYfxiAgY9WTQyvDAVj+pYRgrXSOfN5V1T4+SzN1sJTeg==",
+ "requires": {
+ "warning": "^3.0.0"
+ }
+ },
+ "jss-vendor-prefixer": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/jss-vendor-prefixer/-/jss-vendor-prefixer-7.0.0.tgz",
+ "integrity": "sha512-Agd+FKmvsI0HLcYXkvy8GYOw3AAASBUpsmIRvVQheps+JWaN892uFOInTr0DRydwaD91vSSUCU4NssschvF7MA==",
+ "requires": {
+ "css-vendor": "^0.3.8"
+ }
+ },
"jsx-ast-utils": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz",
@@ -7758,6 +7894,12 @@
"safe-buffer": "^5.0.1"
}
},
+ "kebab-case": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.0.tgz",
+ "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=",
+ "dev": true
+ },
"keymaster": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/keymaster/-/keymaster-1.6.2.tgz",
@@ -9690,6 +9832,18 @@
"invariant": "^2.1.1"
}
},
+ "react-jss": {
+ "version": "8.6.1",
+ "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz",
+ "integrity": "sha512-SH6XrJDJkAphp602J14JTy3puB2Zxz1FkM3bKVE8wON+va99jnUTKWnzGECb3NfIn9JPR5vHykge7K3/A747xQ==",
+ "requires": {
+ "hoist-non-react-statics": "^2.5.0",
+ "jss": "^9.7.0",
+ "jss-preset-default": "^4.3.0",
+ "prop-types": "^15.6.0",
+ "theming": "^1.3.0"
+ }
+ },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
@@ -11168,6 +11322,17 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
+ "theming": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/theming/-/theming-1.3.0.tgz",
+ "integrity": "sha512-ya5Ef7XDGbTPBv5ENTwrwkPUexrlPeiAg/EI9kdlUAZhNlRbCdhMKRgjNX1IcmsmiPcqDQZE6BpSaH+cr31FKw==",
+ "requires": {
+ "brcast": "^3.0.1",
+ "is-function": "^1.0.1",
+ "is-plain-object": "^2.0.1",
+ "prop-types": "^15.5.8"
+ }
+ },
"throttleit": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
diff --git a/package.json b/package.json
index ee2b12e99..8ec2d4f67 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"private": true,
"scripts": {
"prestart": "npm run rebuild",
- "start": "DEBUG=Franz:* electron ./build",
+ "start": "electron ./build",
"start:local": "cross-env LOCAL_API=1 npm start",
"start:live": "cross-env LIVE_API=1 npm start",
"dev": "cross-env NODE_ENV=development gulp dev",
@@ -67,6 +67,7 @@
"react-dropzone": "^4.2.1",
"react-electron-web-view": "^2.0.1",
"react-intl": "^2.3.0",
+ "react-jss": "8.6.1",
"react-loader": "^2.4.0",
"react-router": "^3.0.2",
"react-router-transition": "^0.1.1",
@@ -108,7 +109,9 @@
"gulp-sass": "^4.0.2",
"gulp-sass-variables": "^1.1.1",
"gulp-server-livereload": "^1.9.2",
+ "hex-rgb": "3.0.0",
"husky": "^1.1.4",
+ "kebab-case": "1.0.0",
"node-sass": "^4.7.2",
"prettier": "1.15.2"
},
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 46b2f82fc..d8b410aaf 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -32,8 +32,7 @@ const messages = defineMessages({
},
});
-@inject('stores') @observer
-export default class SettingsNavigation extends Component {
+export default @inject('stores') @observer class SettingsNavigation extends Component {
static propTypes = {
serviceCount: PropTypes.number.isRequired,
};
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index affc1a0a2..c5c9c6850 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -1,6 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { inject, observer } from 'mobx-react';
+import { ThemeProvider } from 'react-jss';
import AppStore from '../../stores/AppStore';
import RecipesStore from '../../stores/RecipesStore';
@@ -109,26 +110,28 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
);
return (
-
- {React.Children.count(children) > 0 ? children : null}
-
+
+
+ {React.Children.count(children) > 0 ? children : null}
+
+
);
}
}
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index bee6c8bcf..d37ebe4c7 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -1,6 +1,8 @@
import { action, observable, computed } from 'mobx';
import Store from './lib/Store';
+import * as themeDefault from '../theme/default';
+import * as themeDark from '../theme/dark';
export default class UIStore extends Store {
@observable showServicesUpdatedInfoBar = false;
@@ -20,6 +22,14 @@ export default class UIStore extends Store {
return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted;
}
+ @computed get theme() {
+ if (this.stores.settings.all.app.darkMode) {
+ return Object.assign({}, themeDefault, themeDark);
+ }
+
+ return themeDefault;
+ }
+
// Actions
@action _openSettings({ path = '/settings' }) {
const settingsPath = path !== '/settings' ? `/settings/${path}` : path;
diff --git a/src/styles/colors.scss b/src/styles/colors.scss
index 4411a0e81..80c2fb633 100644
--- a/src/styles/colors.scss
+++ b/src/styles/colors.scss
@@ -1,38 +1,40 @@
-$theme-brand-primary: #3498db;
-$theme-brand-success: #5cb85c;
-$theme-brand-info: #5bc0de;
-$theme-brand-warning: #FF9F00;
-$theme-brand-danger: #d9534f;
+@import "./type-helper";
-$theme-gray-dark: #373a3c;
-$theme-gray: #55595c;
-$theme-gray-light: #818a91;
-$theme-gray-lighter: #eceeef;
-$theme-gray-lightest: #f7f7f9;
+$theme-brand-primary: convert-rgb-string-to-color($raw-theme-brand-primary);
+$theme-brand-success: convert-rgb-string-to-color($raw-theme-brand-success);
+$theme-brand-info: convert-rgb-string-to-color($raw-theme-brand-info);
+$theme-brand-warning: convert-rgb-string-to-color($raw-theme-brand-warning);
+$theme-brand-danger: convert-rgb-string-to-color($raw-theme-brand-danger);
-$theme-border-radius: 6px;
-$theme-border-radius-small: 3px;
+$theme-gray-dark: convert-rgb-string-to-color($raw-theme-gray-dark);
+$theme-gray: convert-rgb-string-to-color($raw-theme-gray);
+$theme-gray-light: convert-rgb-string-to-color($raw-theme-gray-light);
+$theme-gray-lighter: convert-rgb-string-to-color($raw-theme-gray-lighter);
+$theme-gray-lightest: convert-rgb-string-to-color($raw-theme-gray-lightest);
-$theme-sidebar-width: 68px;
+$theme-border-radius: to-number($raw-theme-border-radius);
+$theme-border-radius-small: to-number($raw-theme-border-radius-small);
-$theme-text-color: $theme-gray-dark;
+$theme-sidebar-width: to-number($raw-theme-sidebar-width);
+
+$theme-text-color: convert-rgb-string-to-color($raw-theme-gray-dark);
$theme-transition-time: .5s;
$theme-inset-shadow: inset 0 2px 5px rgba(0, 0, 0, .03);
// Dark Theme
-$dark-theme-black: #1A1A1A;
+$dark-theme-black: convert-rgb-string-to-color($raw-dark-theme-black);
-$dark-theme-gray-darkest: #1E1E1E;
-$dark-theme-gray-darker: #2D2F31;
-$dark-theme-gray-dark: #383A3B;
+$dark-theme-gray-darkest: convert-rgb-string-to-color($raw-dark-theme-gray-darkest);
+$dark-theme-gray-darker: convert-rgb-string-to-color($raw-dark-theme-gray-darker);
+$dark-theme-gray-dark: convert-rgb-string-to-color($raw-dark-theme-gray-dark);
-$dark-theme-gray: #47494B;
+$dark-theme-gray: convert-rgb-string-to-color($raw-dark-theme-gray);
-$dark-theme-gray-light: #515355;
-$dark-theme-gray-lighter: #8a8b8b;
-$dark-theme-gray-lightest: #FFF;
+$dark-theme-gray-light: convert-rgb-string-to-color($raw-dark-theme-gray-light);
+$dark-theme-gray-lighter: convert-rgb-string-to-color($raw-dark-theme-gray-lighter);
+$dark-theme-gray-lightest: convert-rgb-string-to-color($raw-dark-theme-gray-lightest);
-$dark-theme-gray-smoke: #CED0D1;
-$dark-theme-text-color: #FFF;
+$dark-theme-gray-smoke: convert-rgb-string-to-color($raw-dark-theme-gray-smoke);
+$dark-theme-text-color: convert-rgb-string-to-color($raw-dark-theme-text-color);
diff --git a/src/styles/type-helper.scss b/src/styles/type-helper.scss
new file mode 100644
index 000000000..b1da394b5
--- /dev/null
+++ b/src/styles/type-helper.scss
@@ -0,0 +1,100 @@
+@function str-split($string, $separator) {
+ // empty array/list
+ $split-arr: ();
+ // first index of separator in string
+ $index : str-index($string, $separator);
+ // loop through string
+ @while $index != null {
+ // get the substring from the first character to the separator
+ $item: str-slice($string, 1, $index - 1);
+ // push item to array
+ $split-arr: append($split-arr, $item);
+ // remove item and separator from string
+ $string: str-slice($string, $index + 1);
+ // find new index of separator
+ $index : str-index($string, $separator);
+ }
+ // add the remaining string to list (the last item)
+ $split-arr: append($split-arr, $string);
+
+ @return $split-arr;
+}
+
+// ----
+// Sass (v3.4.13)
+// Compass (v1.0.3)
+// ----
+
+/// String to number converter
+/// @author Hugo Giraudel
+/// @access private
+
+
+/// Casts a string into a number
+///
+/// @param {String | Number} $value - Value to be parsed
+///
+/// @return {Number}
+
+@function to-number($value) {
+ @if type-of($value) == 'number' {
+ @return $value;
+ } @else if type-of($value) != 'string' {
+ $_: log('Value for `to-number` should be a number or a string.');
+ }
+
+ $result: 0;
+ $digits: 0;
+ $minus: str-slice($value, 1, 1) == '-';
+ $numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9);
+
+ @for $i from if($minus, 2, 1) through str-length($value) {
+ $character: str-slice($value, $i, $i);
+
+ @if not (index(map-keys($numbers), $character) or $character == '.') {
+ @return to-length(if($minus, -$result, $result), str-slice($value, $i))
+ }
+
+ @if $character == '.' {
+ $digits: 1;
+ } @else if $digits == 0 {
+ $result: $result * 10 + map-get($numbers, $character);
+ } @else {
+ $digits: $digits * 10;
+ $result: $result + map-get($numbers, $character) / $digits;
+ }
+ }
+
+ @return if($minus, -$result, $result);;
+}
+
+
+/// Add `$unit` to `$value`
+///
+/// @param {Number} $value - Value to add unit to
+/// @param {String} $unit - String representation of the unit
+///
+/// @return {Number} - `$value` expressed in `$unit`
+@function to-length($value, $unit) {
+ $units: ('px': 1px, 'cm': 1cm, 'mm': 1mm, '%': 1%, 'ch': 1ch, 'pc': 1pc, 'in': 1in, 'em': 1em, 'rem': 1rem, 'pt': 1pt, 'ex': 1ex, 'vw': 1vw, 'vh': 1vh, 'vmin': 1vmin, 'vmax': 1vmax);
+
+ @if not index(map-keys($units), $unit) {
+ $_: log('Invalid unit `#{$unit}`.');
+ }
+
+ @return $value * map-get($units, $unit);
+}
+
+
+
+/// converts injectes rgb strings to sass colors
+@function convert-rgb-string-to-color($string) {
+ $values: str-split($string, ',');
+ $colorList: ();
+ @each $value in $values {
+ $colorList: append($colorList, to-number($value));
+ }
+
+ $rgbaColor: rgb(nth($colorList, 1), nth($colorList, 2), nth($colorList, 3));
+ @return $rgbaColor;
+}
\ No newline at end of file
diff --git a/src/theme/dark/index.js b/src/theme/dark/index.js
new file mode 100644
index 000000000..e0e017c7c
--- /dev/null
+++ b/src/theme/dark/index.js
@@ -0,0 +1,5 @@
+import * as legacyStyles from '../default/legacy';
+
+export const colorBackground = legacyStyles.darkThemeGrayDarkest;
+
+export const colorHeadline = legacyStyles.darkThemeTextColor;
diff --git a/src/theme/default/index.js b/src/theme/default/index.js
new file mode 100644
index 000000000..f8b6e898d
--- /dev/null
+++ b/src/theme/default/index.js
@@ -0,0 +1,12 @@
+import * as legacyStyles from './legacy';
+
+/* legacy config, injected into sass */
+export const themeBrandPrimary = '#3498db';
+export const themeBrandSuccess = '#5cb85c';
+export const themeBrandInfo = '#5bc0de';
+export const themeBrandWarning = '#FF9F00';
+export const themeBrandDanger = '#d9534f';
+
+export const colorBackground = legacyStyles.themeGrayLighter;
+
+export const colorHeadline = legacyStyles.themeGrayDark;
diff --git a/src/theme/default/legacy.js b/src/theme/default/legacy.js
new file mode 100644
index 000000000..b676dc1d9
--- /dev/null
+++ b/src/theme/default/legacy.js
@@ -0,0 +1,39 @@
+/* legacy config, injected into sass */
+export const themeBrandPrimary = '#3498db';
+export const themeBrandSuccess = '#5cb85c';
+export const themeBrandInfo = '#5bc0de';
+export const themeBrandWarning = '#FF9F00';
+export const themeBrandDanger = '#d9534f';
+
+export const themeGrayDark = '#373a3c';
+export const themeGray = '#55595c';
+export const themeGrayLight = '#818a91';
+export const themeGrayLighter = '#eceeef';
+export const themeGrayLightest = '#f7f7f9';
+
+export const themeBorderRadius = '6px';
+export const themeBorderRadiusSmall = '3px';
+
+export const themeSidebarWidth = '68px';
+
+export const themeTextColor = themeGrayDark;
+
+export const themeTransitionTime = '.5s';
+
+export const themeInsetShadow = 'inset 0 2px 5px rgba(0, 0, 0, .03)';
+
+
+export const darkThemeBlack = '#1A1A1A';
+
+export const darkThemeGrayDarkest = '#1E1E1E';
+export const darkThemeGrayDarker = '#2D2F31';
+export const darkThemeGrayDark = '#383A3B';
+
+export const darkThemeGray = '#47494B';
+
+export const darkThemeGrayLight = '#515355';
+export const darkThemeGrayLighter = '#8a8b8b';
+export const darkThemeGrayLightest = '#FFFFFF';
+
+export const darkThemeGraySmoke = '#CED0D1';
+export const darkThemeTextColor = '#FFFFFF';