@rize-finance/storybook-addon-dynamic-theme
Match the Storybook UI to the component theme
npm install @rize-finance/storybook-addon-dynamic-theme
0
Downloads per week
Readme View on GitHub
@rize-finance/storybook-addon-dynamic-theme
Match the Storybook UI theme with your dynamic, context-based component theme.
This addon works together with the excellent contexts addon to apply your custom theme's colors to the Storybook UI theme.
To use it:
-
set up the contexts addon as described in its README.
-
install this addon
yarn add -D @rize-finance/storybook-addon-dynamic-theme
-
register via the addons section of
main.js
- use the addParameters api to set the theme and define the themeTranslation
Example
.storybook/main.js
module.exports = {
stories: ["../src/**/*.stories.tsx"],
addons: [
"@storybook/addon-contexts/register",
"@rize-finance/storybook-addon-dynamic-theme"
]
};
.storybook/contexts.js
import { ThemeProvider } from "emotion-theming";
import { themes } from "../src/style/theme"; // your custom themes
export const themeTitle = "Themes";
export const themePropName = "theme";
export const themeDefault = themes.light;
export const contexts = [
{
icon: "mirror", // a icon displayed in the Storybook toolbar to control contextual props
title: themeTitle, // an unique name of a contextual environment
components: [
// an array of components that is going to be injected to wrap stories
ThemeProvider
],
params: [
// an array of params contains a set of predefined `props` for `components`
{
name: "Light Theme",
props: { [themePropName]: themes.light },
default: true
},
{ name: "Dark Theme", props: { [themePropName]: themes.dark } }
],
options: {
deep: true, // pass the `props` deeply into all wrapping components
disable: false, // disable this contextual environment completely
cancelable: false // allow this contextual environment to be opt-out optionally in toolbar
}
}
];
.storybook/preview.js
import React from "react";
import { addDecorator, addParameters } from "@storybook/react";
import { create } from "@storybook/theming";
import { withContexts } from "@storybook/addon-contexts/react";
import { translateTheme } from "@rize-finance/storybook-addon-dynamic-theme";
import { contexts, themeTitle, themePropName, themeDefault } from "./contexts";
const baseTheme = create({
brandTitle: "Components"
});
const themeTranslation = {
contextPath: [themeTitle, themePropName],
static: baseTheme,
dynamic: {
base: "colors.base",
colorPrimary: "colors.main",
appContentBg: "colors.background",
appBg: "colors.lineWeak",
colorSecondary: "colors.secondary",
appBorderColor: "colors.lineStrong",
appBorderRadius: "borderRadius",
fontBase: "fontBase",
fontCode: "monospace",
textColor: "colors.text",
textInverseColor: "colors.textInverse",
barTextColor: "colors.text",
barSelectedColor: "colors.textStrong",
barBg: "colors.line",
inputBg: "colors.background",
inputBorder: "colors.line",
inputTextColor: "colors.text"
}
};
const theme = translateTheme(themeDefault, themeTranslation);
addParameters({
options: { theme },
themeTranslation
});
addDecorator(withContexts(contexts));
src/style/theme.js
const light = {
colors: {
base: "light",
main: "red",
secondary: "blue",
background: "white",
lineWeak: "#eee",
line: "#ddd",
lineStrong: "#ccc",
text: "#222",
textStrong: "#111",
textInverse: "#eee"
},
borderRadius: 0,
fontBase: '"Open Sans", sans-serif'
};
const dark = {
colors: {
base: "dark",
main: "blue",
secondary: "red",
background: "black",
lineWeak: "#111",
line: "#222",
lineStrong: "#333",
text: "#ddd",
textStrong: "#eee",
textInverse: "#111"
},
borderRadius: 0,
fontBase: '"Open Sans", sans-serif'
};
export const themes = {
light,
dark
};
The important part is the themeTranslation
object.
-
contextPath
: locates the theme within the full context -
static
: parts of the Storybook theme which don't change with context -
dynamic
: mapping from custom theme to Storybook theme- key is a Storybook theme property
- value is the lodash get path to locate the desired property from the custom theme