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

Implement global dark theme #28445

Merged
merged 14 commits into from
Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dev/build/tasks/transpile_scss_task.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const TranspileScssTask = {

try {
const bundles = await buildAll(uiExports.styleSheetPaths, log, build.resolvePath('built_assets/css'));
bundles.forEach(bundle => log.info(`Compiled SCSS: ${bundle.source}`));
bundles.forEach(bundle => log.info(`Compiled SCSS: ${bundle.sourcePath} (theme=${bundle.theme})`));
} catch (error) {
const { message, line, file } = error;
throw new Error(`${message} on line ${line} of ${file}`);
Expand Down
4 changes: 3 additions & 1 deletion src/dev/notice/generate_notice_from_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export async function generateNoticeFromSource({ productName, directory, log })
let match;
while ((match = NOTICE_COMMENT_RE.exec(source)) !== null) {
log.info(`Found @notice comment in ${file.relative}`);
noticeComments.push(match[1]);
if (!noticeComments.includes(match[1])) {
noticeComments.push(match[1]);
}
}
})
.on('error', reject)
Expand Down
9 changes: 9 additions & 0 deletions src/legacy/core_plugins/kibana/ui_setting_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,15 @@ export function getUiSettingDefaults() {
},
}),
},
'theme:darkMode': {
name: i18n.translate('kbn.advancedSettings.darkModeTitle', {
defaultMessage: 'Dark mode',
}),
value: false,
description: i18n.translate('kbn.advancedSettings.darkModeText', {
defaultMessage: `Enable a dark mode for the Kibana UI. A page refresh is required for the setting to be applied.`,
}),
},
'filters:pinnedByDefault': {
name: i18n.translate('kbn.advancedSettings.pinFiltersTitle', {
defaultMessage: 'Pin filters by default',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { fetchFields } from '../lib/fetch_fields';
import chrome from 'ui/chrome';
import { I18nProvider } from '@kbn/i18n/react';

const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');

class VisEditor extends Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -117,7 +119,7 @@ class VisEditor extends Component {
<I18nProvider>
<Visualization
dateFormat={this.props.config.get('dateFormat')}
reversed={false}
reversed={IS_DARK_THEME}
onBrush={this.onBrush}
onUiState={this.handleUiState}
uiState={this.props.vis.getUiState()}
Expand Down
34 changes: 32 additions & 2 deletions src/optimize/base_optimizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ const STATS_WARNINGS_FILTER = new RegExp([
'|(chunk .* \\[mini-css-extract-plugin\\]\\\nConflicting order between:)'
].join(''));

function recursiveIssuer(m) {
if (m.issuer) {
return recursiveIssuer(m.issuer);
} else if (m.name) {
return m.name;
} else {
return false;
}
}

export default class BaseOptimizer {
constructor(opts) {
this.logWithMetadata = opts.logWithMetadata || (() => null);
Expand Down Expand Up @@ -239,7 +249,15 @@ export default class BaseOptimizer {
node: { fs: 'empty' },
context: fromRoot('.'),
cache: true,
entry: this.uiBundles.toWebpackEntries(),
entry: {
...this.uiBundles.toWebpackEntries(),
light_theme: [
require.resolve('../ui/public/styles/bootstrap_light.less'),
],
dark_theme: [
require.resolve('../ui/public/styles/bootstrap_dark.less'),
],
},

devtool: this.sourceMaps,
profile: this.profile || false,
Expand All @@ -257,9 +275,21 @@ export default class BaseOptimizer {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
chunks: chunk => chunk.canBeInitial() && chunk.name !== 'light_theme' && chunk.name !== 'dark_theme',
minChunks: 2,
reuseExistingChunk: true
},
light_theme: {
name: 'light_theme',
test: m => m.constructor.name === 'CssModule' && recursiveIssuer(m) === 'light_theme',
chunks: 'all',
enforce: true
},
dark_theme: {
name: 'dark_theme',
test: m => m.constructor.name === 'CssModule' && recursiveIssuer(m) === 'dark_theme',
chunks: 'all',
enforce: true
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions src/server/sass/__fixtures__/index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
@import 'ui/public/styles/styling_constants';

foo {
bar {
display: flex;
background: $euiFocusBackgroundColor;
}
}
23 changes: 16 additions & 7 deletions src/server/sass/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,26 @@ const renderSass = promisify(sass.render);
const writeFile = promisify(fs.writeFile);
const mkdirpAsync = promisify(mkdirp);

const DARK_THEME_IMPORTER = (url) => {
if (url.includes('k6_colors_light')) {
return { file: url.replace('k6_colors_light', 'k6_colors_dark') };
}

return { file: url };
};

export class Build {
constructor(source, log, targetPath) {
this.source = source;
constructor({ sourcePath, log, targetPath, theme }) {
this.sourcePath = sourcePath;
this.log = log;
this.targetPath = targetPath;
this.includedFiles = [source];
this.theme = theme;
this.includedFiles = [sourcePath];
}

/**
* Glob based on source path
*/

async buildIfIncluded(path) {
if (this.includedFiles && this.includedFiles.includes(path)) {
await this.build();
Expand All @@ -56,14 +64,15 @@ export class Build {

async build() {
const rendered = await renderSass({
file: this.source,
file: this.sourcePath,
outFile: this.targetPath,
sourceMap: true,
sourceMapEmbed: true,
includePaths: [
path.resolve(__dirname, '../..'),
path.resolve(__dirname, '../../../node_modules')
]
path.resolve(__dirname, '../../../node_modules'),
],
importer: this.theme === 'dark' ? DARK_THEME_IMPORTER : undefined
});

const prefixed = postcss([ autoprefixer ]).process(rendered.css);
Expand Down
55 changes: 44 additions & 11 deletions src/server/sass/build.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,54 @@ afterEach(async () => {
await del(TMP);
});

it('builds SASS', async () => {
const cssPath = resolve(TMP, 'style.css');
await (new Build(FIXTURE, {
info: () => {},
warn: () => {},
error: () => {},
}, cssPath)).build();

expect(readFileSync(cssPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2'))
.toMatchInlineSnapshot(`
it('builds light themed SASS', async () => {
const targetPath = resolve(TMP, 'style.css');
await new Build({
sourcePath: FIXTURE,
log: {
info: () => {},
warn: () => {},
error: () => {},
},
theme: 'light',
targetPath
}).build();

expect(
readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2')
).toMatchInlineSnapshot(`
"foo bar {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
background: #e6f0f8; }
/*# sourceMappingURL=... */"
`);
});

it('builds dark themed SASS', async () => {
const targetPath = resolve(TMP, 'style.css');
await new Build({
sourcePath: FIXTURE,
log: {
info: () => {},
warn: () => {},
error: () => {},
},
theme: 'dark',
targetPath
}).build();

expect(
readFileSync(targetPath, 'utf8').replace(/(\/\*# sourceMappingURL=).*( \*\/)/, '$1...$2')
).toMatchInlineSnapshot(`
"foo bar {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex; }
display: flex;
background: #191919; }
/*# sourceMappingURL=... */"
`);
});
7 changes: 6 additions & 1 deletion src/server/sass/build_all.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ export async function buildAll(styleSheets, log, buildDir) {
return;
}

const bundle = new Build(styleSheet.localPath, log, resolve(buildDir, styleSheet.publicPath));
const bundle = new Build({
sourcePath: styleSheet.localPath,
log,
theme: styleSheet.theme,
targetPath: resolve(buildDir, styleSheet.publicPath),
});
await bundle.build();

return bundle;
Expand Down
2 changes: 1 addition & 1 deletion src/server/sass/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export async function sassMixin(kbnServer, server, config) {

scssBundles.forEach(bundle => {
bundle.includedFiles.forEach(file => trackedFiles.add(file));
server.log(['info', 'scss'], `Compiled CSS: ${bundle.source}`);
server.log(['info', 'scss'], `Compiled CSS: ${bundle.sourcePath} (theme=${bundle.theme})`);
});
} catch(error) {
const { message, line, file } = error;
Expand Down
20 changes: 2 additions & 18 deletions src/ui/public/autoload/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,9 @@
* under the License.
*/

const theme = require('../theme');

// Kibana UI Framework
require('@kbn/ui-framework/dist/kui_light.css');

// Elastic UI Framework, light theme
const euiThemeLight = require('!!raw-loader!@elastic/eui/dist/eui_theme_k6_light.css');
theme.registerTheme('light', euiThemeLight);

// Elastic UI Framework, dark theme
const euiThemeDark = require('!!raw-loader!@elastic/eui/dist/eui_theme_k6_dark.css');
theme.registerTheme('dark', euiThemeDark);

// Set default theme.
theme.applyTheme('light');

// All Kibana styles inside of the /styles dir
const context = require.context('../styles', false, /[\/\\](?!mixins|variables|_|\.)[^\/\\]+\.less/);
const context = require.context('../styles', false, /[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/);
context.keys().forEach(key => context(key));

// manually require non-less files
require('../styles/disable_animations');
import '../styles/disable_animations';
20 changes: 20 additions & 0 deletions src/ui/public/styles/bootstrap/_colors_dark.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//== Colors
//
//## Gray and brand colors for use across Bootstrap.
@white: #000;
@blue: #4DA1C0;

@brand-primary: #F5F5F5;
@brand-success: #017D73;
@brand-info: @blue;
@brand-warning: #C06C4C;
@brand-danger: #BF4D4D;

@gray-base: #FFF;
@gray-darker: #F5F5F5;
@gray-dark: #ababab;
@gray5: #8A8A8A;
@gray: #444;
@gray-light: darken(#444, 9%);
@gray-lighter: #333;
@gray-lightest: #242424;
20 changes: 20 additions & 0 deletions src/ui/public/styles/bootstrap/_colors_light.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//== Colors
//
//## Gray and brand colors for use across Bootstrap.
@white: #FFF;
@blue: #006BB4;

@brand-primary: #343741;
@brand-success: #017D73;
@brand-info: @blue;
@brand-warning: #F5A700;
@brand-danger: #BD271E;

@gray-base: #000;
@gray-darker: #343741;
@gray-dark: #7b7b7b;
@gray5: #69707D;
@gray: #98A2B3;
@gray-light: lighten(#98A2B3, 9%); // ~#b4b4b4
@gray-lighter: #D3DAE6;
@gray-lightest: #F5F7FA;
23 changes: 0 additions & 23 deletions src/ui/public/styles/bootstrap/_custom_variables.less
Original file line number Diff line number Diff line change
@@ -1,26 +1,3 @@
@import "variables.less";

//== Colors
//
//## Gray and brand colors for use across Bootstrap.
@white: #FFF;
@blue: #006BB4;

@brand-primary: #343741;
@brand-success: #017D73;
@brand-info: @blue;
@brand-warning: #F5A700;
@brand-danger: #BD271E;

@gray-base: #000;
@gray-darker: #343741;
@gray-dark: #7b7b7b;
@gray5: #69707D;
@gray: #98A2B3;
@gray-light: lighten(#98A2B3, 9%); // ~#b4b4b4
@gray-lighter: #D3DAE6;
@gray-lightest: #F5F7FA;

//== Scaffolding
//
// ## Settings for some of the most global styles.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
// There's an audit in the comments to cover what's left to remove.

// Core variables and mixins
@import "variables.less";
@import "_colors_dark.less";
@import "_custom_variables.less";
@import "mixins.less";

Expand Down
Loading