mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Storybook: Support an arbitrary number of themes (#100111)
* support more themes in storybook * default to dark theme * fix type error * change theme in docs container * add TODO * only show extra themes in development mode * add comment
This commit is contained in:
1
.github/renovate.json5
vendored
1
.github/renovate.json5
vendored
@@ -13,7 +13,6 @@
|
||||
"slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
|
||||
"@types/slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
|
||||
"@types/slate", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
|
||||
"storybook-dark-mode", // 4.0.2 causes storybook 8.4 to break with react hooks errors
|
||||
// Temporarily pause updating lerna and nx until we resolve build issues
|
||||
"lerna",
|
||||
"nx"
|
||||
|
||||
@@ -43,7 +43,6 @@ const mainConfig: StorybookConfig = {
|
||||
},
|
||||
},
|
||||
getAbsolutePath('@storybook/addon-storysource'),
|
||||
getAbsolutePath('storybook-dark-mode'),
|
||||
getAbsolutePath('@storybook/addon-webpack5-compiler-swc'),
|
||||
],
|
||||
framework: {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { addons } from '@storybook/manager-api';
|
||||
import { GrafanaDark } from './storybookTheme';
|
||||
import { getThemeById } from '@grafana/data';
|
||||
import { createStorybookTheme } from './storybookTheme';
|
||||
|
||||
const systemTheme = getThemeById('system');
|
||||
addons.setConfig({
|
||||
isFullscreen: false,
|
||||
panelPosition: 'right',
|
||||
@@ -10,5 +12,5 @@ addons.setConfig({
|
||||
sidebar: {
|
||||
showRoots: true,
|
||||
},
|
||||
theme: GrafanaDark,
|
||||
theme: createStorybookTheme(systemTheme),
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Preview } from '@storybook/react';
|
||||
import 'jquery';
|
||||
import { getTimeZone, getTimeZones } from '@grafana/data';
|
||||
import { getBuiltInThemes, getTimeZone, getTimeZones, GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import '../../../public/vendor/flot/jquery.flot.js';
|
||||
import '../../../public/vendor/flot/jquery.flot.selection';
|
||||
@@ -20,10 +20,9 @@ import { ThemedDocsContainer } from '../src/utils/storybook/ThemedDocsContainer'
|
||||
import lightTheme from '../../../public/sass/grafana.light.scss';
|
||||
// @ts-ignore
|
||||
import darkTheme from '../../../public/sass/grafana.dark.scss';
|
||||
import { GrafanaDark, GrafanaLight } from './storybookTheme';
|
||||
|
||||
const handleThemeChange = (theme: any) => {
|
||||
if (theme !== 'light') {
|
||||
const handleThemeChange = (theme: GrafanaTheme2) => {
|
||||
if (theme.colors.mode !== 'light') {
|
||||
lightTheme.unuse();
|
||||
darkTheme.use();
|
||||
} else {
|
||||
@@ -32,14 +31,12 @@ const handleThemeChange = (theme: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const showExtraThemes = process.env.NODE_ENV === 'development';
|
||||
|
||||
const preview: Preview = {
|
||||
decorators: [withTheme(handleThemeChange), withTimeZone()],
|
||||
parameters: {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
darkMode: {
|
||||
dark: GrafanaDark,
|
||||
light: GrafanaLight,
|
||||
},
|
||||
docs: {
|
||||
container: ThemedDocsContainer,
|
||||
},
|
||||
@@ -68,6 +65,19 @@ const preview: Preview = {
|
||||
},
|
||||
},
|
||||
globalTypes: {
|
||||
theme: {
|
||||
name: 'Theme',
|
||||
description: 'Global theme for components',
|
||||
defaultValue: 'system',
|
||||
toolbar: {
|
||||
icon: 'paintbrush',
|
||||
items: getBuiltInThemes(showExtraThemes).map((theme) => ({
|
||||
value: theme.id,
|
||||
title: theme.name,
|
||||
})),
|
||||
showName: true,
|
||||
},
|
||||
},
|
||||
timeZone: {
|
||||
description: 'Set the timezone for the storybook preview',
|
||||
defaultValue: getTimeZone(),
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { GrafanaTheme2, createTheme } from '@grafana/data';
|
||||
//@ts-ignore
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { create } from '@storybook/theming';
|
||||
|
||||
const createStorybookTheme = (theme: GrafanaTheme2) => {
|
||||
export const createStorybookTheme = (theme: GrafanaTheme2) => {
|
||||
return create({
|
||||
base: theme.colors.mode,
|
||||
colorPrimary: theme.colors.primary.main,
|
||||
@@ -38,8 +37,3 @@ const createStorybookTheme = (theme: GrafanaTheme2) => {
|
||||
brandImage: `public/img/grafana_text_logo-${theme.colors.mode}.svg`,
|
||||
});
|
||||
};
|
||||
|
||||
const GrafanaLight = createStorybookTheme(createTheme({ colors: { mode: 'light' } }));
|
||||
const GrafanaDark = createStorybookTheme(createTheme({ colors: { mode: 'dark' } }));
|
||||
|
||||
export { GrafanaLight, GrafanaDark };
|
||||
|
||||
@@ -180,7 +180,6 @@
|
||||
"rollup-plugin-svg-import": "3.0.0",
|
||||
"sass-loader": "16.0.4",
|
||||
"storybook": "^8.4.2",
|
||||
"storybook-dark-mode": "4.0.1",
|
||||
"style-loader": "4.0.0",
|
||||
"typescript": "5.7.3",
|
||||
"webpack": "5.97.1"
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Wrap the DocsContainer for storybook-dark-mode theme switching support.
|
||||
// Wrap the DocsContainer for theme switching support.
|
||||
import { DocsContainer, DocsContextProps } from '@storybook/addon-docs';
|
||||
import * as React from 'react';
|
||||
import { useDarkMode } from 'storybook-dark-mode';
|
||||
|
||||
import { GrafanaLight, GrafanaDark } from '../../../.storybook/storybookTheme';
|
||||
import { getThemeById } from '@grafana/data';
|
||||
|
||||
import { createStorybookTheme } from '../../../.storybook/storybookTheme';
|
||||
import { GlobalStyles } from '../../themes';
|
||||
|
||||
type Props = {
|
||||
@@ -12,10 +13,18 @@ type Props = {
|
||||
};
|
||||
|
||||
export const ThemedDocsContainer = ({ children, context }: Props) => {
|
||||
const dark = useDarkMode();
|
||||
// Default to system theme for pages that don't have associated stories
|
||||
// Currently this is only the case for the docs `Intro` page
|
||||
let themeId = 'system';
|
||||
if (context.componentStories().length > 0) {
|
||||
const story = context.storyById();
|
||||
const { globals } = context.getStoryContext(story);
|
||||
themeId = globals.theme;
|
||||
}
|
||||
const theme = getThemeById(themeId);
|
||||
|
||||
return (
|
||||
<DocsContainer theme={dark ? GrafanaDark : GrafanaLight} context={context}>
|
||||
<DocsContainer theme={createStorybookTheme(theme)} context={context}>
|
||||
<GlobalStyles />
|
||||
{children}
|
||||
</DocsContainer>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Decorator } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import { useDarkMode } from 'storybook-dark-mode';
|
||||
|
||||
import { createTheme, GrafanaTheme2, ThemeContext } from '@grafana/data';
|
||||
import { getThemeById, GrafanaTheme2, ThemeContext } from '@grafana/data';
|
||||
|
||||
import { GlobalStyles } from '../../themes/GlobalStyles/GlobalStyles';
|
||||
|
||||
type SassThemeChangeHandler = (theme: GrafanaTheme2) => void;
|
||||
const ThemeableStory = ({
|
||||
children,
|
||||
handleSassThemeChange,
|
||||
}: React.PropsWithChildren<{ handleSassThemeChange: SassThemeChangeHandler }>) => {
|
||||
const theme = createTheme({ colors: { mode: useDarkMode() ? 'dark' : 'light' } });
|
||||
interface ThemeableStoryProps {
|
||||
themeId: string;
|
||||
handleSassThemeChange: SassThemeChangeHandler;
|
||||
}
|
||||
const ThemeableStory = ({ children, handleSassThemeChange, themeId }: React.PropsWithChildren<ThemeableStoryProps>) => {
|
||||
const theme = getThemeById(themeId);
|
||||
|
||||
handleSassThemeChange(theme);
|
||||
|
||||
@@ -38,4 +38,8 @@ const ThemeableStory = ({
|
||||
export const withTheme =
|
||||
(handleSassThemeChange: SassThemeChangeHandler): Decorator =>
|
||||
// eslint-disable-next-line react/display-name
|
||||
(story) => <ThemeableStory handleSassThemeChange={handleSassThemeChange}>{story()}</ThemeableStory>;
|
||||
(story, context) => (
|
||||
<ThemeableStory themeId={context.globals.theme} handleSassThemeChange={handleSassThemeChange}>
|
||||
{story()}
|
||||
</ThemeableStory>
|
||||
);
|
||||
|
||||
27
yarn.lock
27
yarn.lock
@@ -4129,7 +4129,6 @@ __metadata:
|
||||
slate-plain-serializer: "npm:0.7.13"
|
||||
slate-react: "npm:0.22.10"
|
||||
storybook: "npm:^8.4.2"
|
||||
storybook-dark-mode: "npm:4.0.1"
|
||||
style-loader: "npm:4.0.0"
|
||||
tinycolor2: "npm:1.6.0"
|
||||
tslib: "npm:2.8.1"
|
||||
@@ -7524,7 +7523,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/components@npm:8.4.4, @storybook/components@npm:^8.0.0, @storybook/components@npm:^8.4.2":
|
||||
"@storybook/components@npm:8.4.4, @storybook/components@npm:^8.4.2":
|
||||
version: 8.4.4
|
||||
resolution: "@storybook/components@npm:8.4.4"
|
||||
peerDependencies:
|
||||
@@ -7533,7 +7532,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core-events@npm:^8.0.0, @storybook/core-events@npm:^8.4.2":
|
||||
"@storybook/core-events@npm:^8.4.2":
|
||||
version: 8.4.4
|
||||
resolution: "@storybook/core-events@npm:8.4.4"
|
||||
peerDependencies:
|
||||
@@ -7605,7 +7604,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/icons@npm:^1.2.12, @storybook/icons@npm:^1.2.5":
|
||||
"@storybook/icons@npm:^1.2.12":
|
||||
version: 1.2.12
|
||||
resolution: "@storybook/icons@npm:1.2.12"
|
||||
peerDependencies:
|
||||
@@ -7615,7 +7614,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/manager-api@npm:8.4.4, @storybook/manager-api@npm:^8.0.0, @storybook/manager-api@npm:^8.4.2":
|
||||
"@storybook/manager-api@npm:8.4.4, @storybook/manager-api@npm:^8.4.2":
|
||||
version: 8.4.4
|
||||
resolution: "@storybook/manager-api@npm:8.4.4"
|
||||
peerDependencies:
|
||||
@@ -7766,7 +7765,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/theming@npm:8.4.4, @storybook/theming@npm:^8.0.0, @storybook/theming@npm:^8.4.2":
|
||||
"@storybook/theming@npm:8.4.4, @storybook/theming@npm:^8.4.2":
|
||||
version: 8.4.4
|
||||
resolution: "@storybook/theming@npm:8.4.4"
|
||||
peerDependencies:
|
||||
@@ -28886,22 +28885,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"storybook-dark-mode@npm:4.0.1":
|
||||
version: 4.0.1
|
||||
resolution: "storybook-dark-mode@npm:4.0.1"
|
||||
dependencies:
|
||||
"@storybook/components": "npm:^8.0.0"
|
||||
"@storybook/core-events": "npm:^8.0.0"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/icons": "npm:^1.2.5"
|
||||
"@storybook/manager-api": "npm:^8.0.0"
|
||||
"@storybook/theming": "npm:^8.0.0"
|
||||
fast-deep-equal: "npm:^3.1.3"
|
||||
memoizerific: "npm:^1.11.3"
|
||||
checksum: 10/3225e5bdaba0ea76b65d642202d9712d7de234e3b5673fb46e444892ab114be207dd287778e2002b662ec35bb8153d2624ff280ce51c5299fb13c711431dad40
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"storybook@npm:^8.4.2":
|
||||
version: 8.4.4
|
||||
resolution: "storybook@npm:8.4.4"
|
||||
|
||||
Reference in New Issue
Block a user