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"