From 029a6c64b48bd54afbcfa488047b3ee5e8b2ca05 Mon Sep 17 00:00:00 2001
From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com>
Date: Mon, 17 Feb 2020 10:36:16 +0100
Subject: [PATCH] Storybook: Add color theme and theme switcher (#22005)
* Add color theme and serve static files for storybook
* Add color theme and serve static files for storybook
* Export dark and light theme
* Add storybook-dark-mode package
* Add theme toggle functionality
* Toggle story theme too
* Remove unused import
* webpack config changes not needed
---
.gitignore | 2 +
packages/grafana-ui/.storybook/main.ts | 7 ++-
.../grafana-ui/.storybook/manager-head.html | 1 +
packages/grafana-ui/.storybook/preview.ts | 6 +-
.../grafana-ui/.storybook/static/fav32.png | Bin 0 -> 3607 bytes
.../.storybook/static/grafana_icon.svg | 57 ++++++++++++++++++
.../grafana-ui/.storybook/storybookTheme.ts | 49 +++++++++++++++
packages/grafana-ui/package.json | 5 +-
.../src/utils/storybook/withTheme.tsx | 16 ++---
yarn.lock | 10 ++-
10 files changed, 136 insertions(+), 17 deletions(-)
create mode 100644 packages/grafana-ui/.storybook/manager-head.html
create mode 100644 packages/grafana-ui/.storybook/static/fav32.png
create mode 100644 packages/grafana-ui/.storybook/static/grafana_icon.svg
create mode 100644 packages/grafana-ui/.storybook/storybookTheme.ts
diff --git a/.gitignore b/.gitignore
index 4e08b342d10..40ba75b1092 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,8 @@ awsconfig
/public/views/error.html
/emails/dist
/reports
+.yarnrc
+.yarn/
# Enterprise emails
/emails/templates/enterprise_*
diff --git a/packages/grafana-ui/.storybook/main.ts b/packages/grafana-ui/.storybook/main.ts
index c36e7e70da6..6b9ce060a35 100644
--- a/packages/grafana-ui/.storybook/main.ts
+++ b/packages/grafana-ui/.storybook/main.ts
@@ -1,4 +1,9 @@
module.exports = {
stories: ['../src/**/*.story.{js,jsx,ts,tsx,mdx}'],
- addons: ['@storybook/addon-knobs', '@storybook/addon-actions', '@storybook/addon-docs'],
+ addons: [
+ '@storybook/addon-knobs',
+ '@storybook/addon-actions',
+ '@storybook/addon-docs',
+ 'storybook-dark-mode/register',
+ ],
};
diff --git a/packages/grafana-ui/.storybook/manager-head.html b/packages/grafana-ui/.storybook/manager-head.html
new file mode 100644
index 00000000000..469d19e5541
--- /dev/null
+++ b/packages/grafana-ui/.storybook/manager-head.html
@@ -0,0 +1 @@
+
diff --git a/packages/grafana-ui/.storybook/preview.ts b/packages/grafana-ui/.storybook/preview.ts
index a14d1b11e38..4d0aaca0925 100644
--- a/packages/grafana-ui/.storybook/preview.ts
+++ b/packages/grafana-ui/.storybook/preview.ts
@@ -14,6 +14,7 @@ import { withPaddedStory } from '../src/utils/storybook/withPaddedStory';
import lightTheme from '../../../public/sass/grafana.light.scss';
// @ts-ignore
import darkTheme from '../../../public/sass/grafana.dark.scss';
+import { GrafanaLight, GrafanaDark } from './storybookTheme';
import { configure, addDecorator, addParameters } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
@@ -26,13 +27,16 @@ const handleThemeChange = (theme: any) => {
lightTheme.use();
}
};
-
addDecorator(withTheme(handleThemeChange));
addDecorator(withKnobs);
addDecorator(withPaddedStory);
addParameters({
info: {},
+ darkMode: {
+ dark: GrafanaDark,
+ light: GrafanaLight,
+ },
options: {
showPanel: true,
showRoots: true,
diff --git a/packages/grafana-ui/.storybook/static/fav32.png b/packages/grafana-ui/.storybook/static/fav32.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f5f809d9cb809a0fc56a130ac6c60a496368ccd
GIT binary patch
literal 3607
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
literal 0
HcmV?d00001
diff --git a/packages/grafana-ui/.storybook/static/grafana_icon.svg b/packages/grafana-ui/.storybook/static/grafana_icon.svg
new file mode 100644
index 00000000000..e91f3abdb41
--- /dev/null
+++ b/packages/grafana-ui/.storybook/static/grafana_icon.svg
@@ -0,0 +1,57 @@
+
+
+
diff --git a/packages/grafana-ui/.storybook/storybookTheme.ts b/packages/grafana-ui/.storybook/storybookTheme.ts
new file mode 100644
index 00000000000..9490fe2c6db
--- /dev/null
+++ b/packages/grafana-ui/.storybook/storybookTheme.ts
@@ -0,0 +1,49 @@
+//@ts-ignore
+import { create } from '@storybook/theming/create';
+import lightTheme from '../src/themes/light';
+import darkTheme from '../src/themes/dark';
+import ThemeCommons from '../src/themes/default';
+import { GrafanaTheme } from '@grafana/data';
+
+const createTheme = (theme: GrafanaTheme) => {
+ return create({
+ base: theme.name.includes('Light') ? 'light' : 'dark',
+
+ colorPrimary: theme.colors.brandPrimary,
+ colorSecondary: theme.colors.brandPrimary,
+
+ // UI
+ appBg: theme.colors.bodyBg,
+ appContentBg: theme.colors.bodyBg,
+ appBorderColor: theme.colors.pageHeaderBorder,
+ appBorderRadius: 4,
+
+ // Typography
+ fontBase: ThemeCommons.typography.fontFamily.sansSerif,
+ fontCode: ThemeCommons.typography.fontFamily.monospace,
+
+ // Text colors
+ textColor: theme.colors.text,
+ textInverseColor: 'rgba(255,255,255,0.9)',
+
+ // Toolbar default and active colors
+ barTextColor: theme.colors.formInputBorderActive,
+ barSelectedColor: theme.colors.brandPrimary,
+ barBg: theme.colors.bodyBg,
+
+ // Form colors
+ inputBg: theme.colors.formInputBg,
+ inputBorder: theme.colors.formInputBorder,
+ inputTextColor: theme.colors.formInputText,
+ inputBorderRadius: 4,
+
+ brandTitle: 'Grafana UI',
+ brandUrl: '/',
+ brandImage: '/grafana_icon.svg',
+ });
+};
+
+const GrafanaLight = createTheme(lightTheme);
+const GrafanaDark = createTheme(darkTheme);
+
+export { GrafanaLight, GrafanaDark };
diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json
index 92ecc1bc585..eb3139816f5 100644
--- a/packages/grafana-ui/package.json
+++ b/packages/grafana-ui/package.json
@@ -18,8 +18,8 @@
"scripts": {
"lint": "eslint .storybook/ src/ --ext=.js,.ts,.tsx",
"typecheck": "tsc --noEmit",
- "storybook": "start-storybook -p 9001 -c .storybook",
- "storybook:build": "build-storybook -o ./dist/storybook -c .storybook",
+ "storybook": "start-storybook -p 9001 -c .storybook -s .storybook/static",
+ "storybook:build": "build-storybook -o ./dist/storybook -c .storybook -s .storybook/static",
"clean": "rimraf ./dist ./compiled",
"bundle": "rollup -c rollup.config.ts",
"build": "grafana-toolkit package:build --scope=ui"
@@ -92,6 +92,7 @@
"rollup-plugin-terser": "4.0.4",
"rollup-plugin-typescript2": "0.19.3",
"rollup-plugin-visualizer": "0.9.2",
+ "storybook-dark-mode": "0.3.0",
"ts-loader": "6.2.1",
"typescript": "3.7.2"
},
diff --git a/packages/grafana-ui/src/utils/storybook/withTheme.tsx b/packages/grafana-ui/src/utils/storybook/withTheme.tsx
index e004df46437..341bf70be6e 100644
--- a/packages/grafana-ui/src/utils/storybook/withTheme.tsx
+++ b/packages/grafana-ui/src/utils/storybook/withTheme.tsx
@@ -1,28 +1,20 @@
import React from 'react';
import { ThemeContext } from '../../themes/ThemeContext';
-import { select } from '@storybook/addon-knobs';
import { getTheme } from '../../themes/index';
import { GrafanaThemeType } from '@grafana/data';
import { RenderFunction } from '../../types';
+import { useDarkMode } from 'storybook-dark-mode';
type SassThemeChangeHandler = (theme: GrafanaThemeType) => void;
const ThemableStory: React.FunctionComponent<{ handleSassThemeChange: SassThemeChangeHandler }> = ({
children,
handleSassThemeChange,
}) => {
- const themeKnob = select(
- 'Theme',
- {
- Light: GrafanaThemeType.Light,
- Dark: GrafanaThemeType.Dark,
- },
- GrafanaThemeType.Dark,
- 'Theme'
- );
+ const theme = useDarkMode() ? GrafanaThemeType.Dark : GrafanaThemeType.Light;
- handleSassThemeChange(themeKnob);
+ handleSassThemeChange(theme);
- return {children};
+ return {children};
};
// Temporary solution. When we update to Storybook V5 we will be able to pass data from decorator to story
diff --git a/yarn.lock b/yarn.lock
index ea54e6deb4f..612a28543ef 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11381,7 +11381,7 @@ fast-deep-equal@^2.0.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
-fast-deep-equal@^3.1.1:
+fast-deep-equal@^3.0.0, fast-deep-equal@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
@@ -22783,6 +22783,14 @@ storybook-chromatic@^2.2.2:
tree-kill "^1.1.0"
uuid "^3.3.2"
+storybook-dark-mode@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/storybook-dark-mode/-/storybook-dark-mode-0.3.0.tgz#9a6ce2c55e68b2dfbd3e9af73f8c92cfcb87f23a"
+ integrity sha512-95uIZqncsCRdakqgO0roWn5orJixtTBIAtkDl8rrIsaEm4N2U68xodCe3VqQmCf646vmculel1sba7qgavN+Xw==
+ dependencies:
+ fast-deep-equal "^3.0.0"
+ memoizerific "^1.11.3"
+
stream-browserify@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"