storybook-addon-theme-playground
is a theme addon for storybook. It provides a panel where theme values can be tweaked directly.
- 🎛 Seperate panel with auto-generated controls for each theme value
- 🧬 Customizable controls based on your needs
npm install -D storybook-addon-theme-playground
yarn add -D storybook-addon-theme-playground
Add to .storybook/main.js
module.exports = {
addons: ["storybook-addon-theme-playground"],
};
Add to .storybook/preview.js
.
// Import a theme provider of your choice
import { ThemeProvider } from "styled-components";
import theme from "path/to/theme";
export const parameters = {
themePlayground: {
theme,
provider: ThemeProvider,
},
};
To add multiple themes, add an Array
to the theme
key. Each theme must have a name
and a theme
key.
import { ThemeProvider } from "styled-components";
import defaultTheme from "path/to/default/theme";
import anotherTheme from "path/to/another/theme";
export const parameters = {
themePlayground: {
theme: [
{ name: "Default Theme", theme: defaultTheme },
{ name: "Another Theme", theme: anotherTheme },
],
provider: ThemeProvider,
},
};
object
| Array<{ name: string, theme: object }>
| required
The theme object
or multiple themes as an array
of objects
.
any
| required
Any provider component which will accept a theme object prop and children. storybook-addon-theme-playground
has no default provider due to extendability.
object
| optional
Optional control components of default controls. Look at the controls section for detailed documentation.
object
| optional
An additional config object can be added. Look at the Config section for detailed documentation.
"path" || "startCase" || (path: string[]) => string
| default: "startCase"
boolean
| default: true
Set to false
updating the theme values will not be debounced.
number
| default: 500
boolean
| default: true
Set to false
no code component will be rendered.
boolean
| default: false
Shows the difference between initial theme and modified theme. Currently in an experimental state. Rendering multiple global styles for example override each other.
boolean
| default: false
Set to true
to disable addon panel for single stories.
export default {
title: "Disabled story",
parameters: {
themePlayground: { disabled: true },
},
};
Example
import { ThemeProvider } from "styled-components";
export const parameters = {
themePlayground: {
theme: { button: { color: "#000" } },
provider: ThemeProvider,
config: {
// One of "path"
labelFormat: "path", // "button.color"
// or "startCase"
labelFormat: "startCase", // "Button Color"
// or a custom function
labelFormat: (path) => {
// path is equal to ["button", "color"]
return path.join("-"); // "button-color"
},
debounce: true || false,
debounceRate: 500,
showConfig: true || false,
},
},
};
storybook-addon-theme-playground
will render default controls based on the theme value. If you want to customize them, you can override the default controls by adding an controls
object to the parameters.
As a key use the theme object path, e.g 'button.spacing'
.
All controls accept a type
, label
, description
and icon
prop.
You can use all icons from the storybook styleguide.
Example
import { ThemeProvider } from "styled-components";
import theme from "path/to/theme";
const controls = {
"button.spacing": {
type: "number",
icon: "expand",
label: "Button Spacing",
description: "Spacing for all buttons",
min: 1,
max: 20,
steps: 1,
},
"button.color.primary": {
type: "color",
label: "Button Primary Color",
},
};
export const parameters = {
themePlayground: { theme, controls, provider: ThemeProvider },
};
It is also possible to hide specific theme values or objects, e.g.:
const controls = {
breakpoints: {
hidden: true,
},
"button.spacing": {
hidden: true,
},
};
'theme.path': {
type: 'color',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null
}
'theme.path': {
type: 'number',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null,
min: number | 0,
max: number | 100,
steps: number | 1
}
'theme.path': {
type: 'select',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null
options: [
{
value: string | number,
label: string
}
]
}
'theme.path': {
type: 'shorthand',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null
}
'theme.path': {
type: 'switch',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null
}
'theme.path': {
type: 'radio',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null
options: [
{
value: string,
label: string
}
]
}
'theme.path': {
type: 'range',
icon: string,
hidden: boolean,
label: string | 'Theme Path',
description: string | null,
min: number | 0,
max: number | 100,
steps: number | 1
}
storybook-addon-theme-playground
will render the following components based on the value.
boolean
number
string
string
&&string.endsWith("px" || "rem" || "em" || "%")
string
&&string.startsWith("#" || "rgba" || "rgba")
||label.includes("color")
object
&&Object.keys(object).length === 4
&&Object.keys(object).includes("top" && "right" && "bottom" && "left")
// .storybook/preview.ts
import {
withThemePlayground,
ThemePlaygroundProps,
} from "storybook-addon-theme-playground";
import theme from "path/to/theme";
interface ThemePlaygroundParams extends ThemePlaygroundProps {
theme: typeof theme;
}
const params: ThemePlaygroundParams = {
theme,
provider: ThemeProvider,
controls: {
"headline.fontWeight": {
type: "range",
max: 900,
min: 1,
description: "Define the font weight of the variable font",
},
"copy.fontWeight": {
type: "range",
max: 900,
min: 1,
description: "Define the font weight of the variable font",
},
},
};
export const parameters = { themePlayground: params };