如何在 Storybook 6.0 中自定义深色和浅色主题
How to customize both dark and light themes in Storybook 6.0
我正在使用明暗主题制作 PWA,我想创建我的 Storybook 明暗主题来反映这些主题。
所以我创建了一个函数,如果我将 Material UI 主题和基本名称传递给它,它将 return 一个新的 Storybook 主题对象给我。
但是如何将这 2 个对象作为主题传递给 Storybook?
我发现我应该去 manager.js
并添加以下代码
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: createThemeFromMUITheme('light', theme.light),
})
但是如何为浅色和深色设置主题?
我试过了
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: {
light: createThemeFromMUITheme('light', theme.light),
dark: createThemeFromMUITheme('dark', theme.dark)
},
})
但这会使故事书什么都不显示(但它不会失败)
请帮忙:-)
编辑:我也试过以下方法
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: createThemeFromMUITheme('light', theme.light),
})
addons.setConfig({
theme: createThemeFromMUITheme('dark', theme.dark),
})
编辑 #2:来自 createThemeFromMUITheme 的 returned 主题配置对象是有效的 BTW
如果有人想要我制作的将 MUI 主题对象转换为 SB 主题对象的功能 - 那么就是这样...
(我还没有弄乱表格颜色...)
import { create } from '@storybook/theming/create'
const createThemeFromMUITheme = (name, theme) => {
return create({
base: name,
colorPrimary: theme.palette.primary.main,
colorSecondary: theme.palette.secondary.main,
// UI
appBg: theme.palette.background.default,
appContentBg: theme.palette.background.paper,
appBorderColor: theme.palette.background.paper,
appBorderRadius: theme.shape.borderRadius,
// Typography
fontBase: theme.typography.fontFamily,
fontCode: 'monospace',
// Text colors
textColor: theme.palette.text.primary,
textInverseColor: theme.palette.text.secondary,
// Toolbar default and active colors
barTextColor: theme.palette.text.primary,
barSelectedColor: theme.palette.text.secondary,
barBg: theme.palette.background.default,
brandTitle: 'Add your brand title here',
brandUrl: 'https://yourbrandurl.com',
brandImage: 'https://placehold.it/350x150',
})
}
export default createThemeFromMUITheme
您的故事书默认只能显示一个主题
但是您可以使用名为 storybook-dark-mode 的插件在深色和浅色主题之间切换,这是插件页面 here
示例将其放入 preview.js 文件中:
import { addParameters } from '@storybook/react'; // or any other type of storybook
addParameters({
darkMode: {
// Set the initial theme
current: 'light'
// Override the default dark theme
dark: { ...themes.dark, appBg: 'black' },
// Override the default light theme
light: { ...themes.normal, appBg: 'red' }
}
});
然后你的故事书中就会有一个这样的切换按钮
好吧 - 解决方案就在眼前,但像往常一样,我没有充分阅读文档。
我确实安装了 storybook-dark-theme,我的想法是完全集成 MUI,这样浅色主题将显示我的应用程序浅色主题,深色主题将显示我的深色主题 - 组件也是如此.
这样 light/dark 主题切换器就完全全局化了。
不过,它确实比您写的要多一点。
这就是我的目标
你可以从这里下载所有的
Link to my github with the solution
当 storybook 第一次呈现时,它将使用默认主题,因此在您已经覆盖的 light/dark 主题开始之前,您会看到一些闪烁。
第一次点击将保持浅色主题,但现在它将使用您的浅色主题。
解决方法是在 manager.ts
中用浅色主题初始化,就像这样
import { addons } from '@storybook/addons'
import { theme as appTheme } from '../src/theme/theme'
import { createThemeFromMuiTheme } from './utils/create-theme-from-mui-theme'
addons.setConfig({
theme: createThemeFromMuiTheme({
theme: appTheme.light,
options: {
base: 'light',
brandTitle: 'Storybook with MUI',
brandUrl: 'https://www.github.com/IgorSzyporyn/storybook-with-mui'
},
})
})
然后在 preview.ts
中,您需要像这样设置 light/dark 覆盖
import React from 'react'
import { addDecorator } from '@storybook/react'
import { theme as appTheme } from '../src/theme/theme'
import { WithMuiTheme } from './components/WithMuiTheme'
import { createThemeFromMuiTheme } from './utils/create-theme-from-mui-theme'
addDecorator((story) => <WithMuiTheme>{story()}</WithMuiTheme>)
export const parameters = {
exportedParameter: 'exportedParameter',
darkMode: {
current: 'light',
light: createThemeFromMuiTheme({ theme: appTheme.light, asStorybookTheme: false }),
dark: createThemeFromMuiTheme({ theme: appTheme.dark, asStorybookTheme: false })
},
}
然后像这样制作你的装饰器包装纸./components/WithMuiThemeProps
import React from 'react'
import { MuiThemeProvider, CssBaseline, StylesProvider } from '@material-ui/core'
import { useThemeType } from '../hooks/UseThemeType'
import { theme } from '../../src/theme/theme'
type WithMuiThemeProps = {
children: React.ReactNode
}
export const WithMuiTheme = ({ children }: WithMuiThemeProps) => {
const themeType = useThemeType()
return (
<MuiThemeProvider theme={theme[themeType]}>
<CssBaseline />
<StylesProvider injectFirst>{children}</StylesProvider>
</MuiThemeProvider>
)
}
这是使更新发生的挂钩 ./hooks/UseThemeType.ts
import React from 'react'
import addons from '@storybook/addons'
const channel = addons.getChannel()
export const useThemeType = () => {
const [isDark, setDark] = React.useState(false)
React.useEffect(() => {
channel.on('DARK_MODE', setDark)
return () => channel.off('DARK_MODE', setDark)
}, [channel, setDark])
const paletteType = isDark ? 'dark' : 'light'
return paletteType
}
最后是./utils/create-theme-from-mui-theme.ts
import { create } from '@storybook/theming/create'
import { Theme } from '@material-ui/core'
type CreateThemFromMuiTheme = {
theme: Theme
options?: Object
asStorybookTheme?: boolean
}
export const createThemeFromMuiTheme = ({
theme,
options = {},
asStorybookTheme = true,
}: CreateThemFromMuiTheme) => {
const themeValue = {
colorPrimary: theme.palette.primary.main,
colorSecondary: theme.palette.secondary.main,
// UI
appBg: theme.palette.background.paper,
appContentBg: theme.palette.background.default,
appBorderColor: theme.palette.background.paper,
appBorderRadius: theme.shape.borderRadius,
// Typography
fontBase: theme.typography.fontFamily,
fontCode: 'monospace',
// Text colors
textColor: theme.palette.text.primary,
textInverseColor: theme.palette.text.secondary,
// Toolbar default and active colors
barTextColor: theme.palette.text.secondary,
barSelectedColor: theme.palette.secondary.main,
barBg: theme.palette.background.default,
// Form color
inputBg: 'transparent',
inputBorder: 'silver',
inputTextColor: theme.palette.text.primary,
inputBorderRadius: theme.shape.borderRadius,
...options,
}
return asStorybookTheme ? create(themeValue) : themeValue
}
现在您将能够使用完全集成到 Storybook 中的主题 - 当您切换 Storybook 主题时,Storybook 本身将更改为主题,您使用的组件也会更改。
我正在使用明暗主题制作 PWA,我想创建我的 Storybook 明暗主题来反映这些主题。
所以我创建了一个函数,如果我将 Material UI 主题和基本名称传递给它,它将 return 一个新的 Storybook 主题对象给我。
但是如何将这 2 个对象作为主题传递给 Storybook?
我发现我应该去 manager.js
并添加以下代码
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: createThemeFromMUITheme('light', theme.light),
})
但是如何为浅色和深色设置主题?
我试过了
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: {
light: createThemeFromMUITheme('light', theme.light),
dark: createThemeFromMUITheme('dark', theme.dark)
},
})
但这会使故事书什么都不显示(但它不会失败)
请帮忙:-)
编辑:我也试过以下方法
import theme from '../src/theme/theme'
import createThemeFromMUITheme from './create-theme-from-mui-theme'
import addons from '@storybook/addons'
addons.setConfig({
theme: createThemeFromMUITheme('light', theme.light),
})
addons.setConfig({
theme: createThemeFromMUITheme('dark', theme.dark),
})
编辑 #2:来自 createThemeFromMUITheme 的 returned 主题配置对象是有效的 BTW
如果有人想要我制作的将 MUI 主题对象转换为 SB 主题对象的功能 - 那么就是这样...
(我还没有弄乱表格颜色...)
import { create } from '@storybook/theming/create'
const createThemeFromMUITheme = (name, theme) => {
return create({
base: name,
colorPrimary: theme.palette.primary.main,
colorSecondary: theme.palette.secondary.main,
// UI
appBg: theme.palette.background.default,
appContentBg: theme.palette.background.paper,
appBorderColor: theme.palette.background.paper,
appBorderRadius: theme.shape.borderRadius,
// Typography
fontBase: theme.typography.fontFamily,
fontCode: 'monospace',
// Text colors
textColor: theme.palette.text.primary,
textInverseColor: theme.palette.text.secondary,
// Toolbar default and active colors
barTextColor: theme.palette.text.primary,
barSelectedColor: theme.palette.text.secondary,
barBg: theme.palette.background.default,
brandTitle: 'Add your brand title here',
brandUrl: 'https://yourbrandurl.com',
brandImage: 'https://placehold.it/350x150',
})
}
export default createThemeFromMUITheme
您的故事书默认只能显示一个主题 但是您可以使用名为 storybook-dark-mode 的插件在深色和浅色主题之间切换,这是插件页面 here
示例将其放入 preview.js 文件中:
import { addParameters } from '@storybook/react'; // or any other type of storybook
addParameters({
darkMode: {
// Set the initial theme
current: 'light'
// Override the default dark theme
dark: { ...themes.dark, appBg: 'black' },
// Override the default light theme
light: { ...themes.normal, appBg: 'red' }
}
});
然后你的故事书中就会有一个这样的切换按钮
好吧 - 解决方案就在眼前,但像往常一样,我没有充分阅读文档。
我确实安装了 storybook-dark-theme,我的想法是完全集成 MUI,这样浅色主题将显示我的应用程序浅色主题,深色主题将显示我的深色主题 - 组件也是如此.
这样 light/dark 主题切换器就完全全局化了。
不过,它确实比您写的要多一点。
这就是我的目标
你可以从这里下载所有的 Link to my github with the solution
当 storybook 第一次呈现时,它将使用默认主题,因此在您已经覆盖的 light/dark 主题开始之前,您会看到一些闪烁。
第一次点击将保持浅色主题,但现在它将使用您的浅色主题。
解决方法是在 manager.ts
中用浅色主题初始化,就像这样
import { addons } from '@storybook/addons'
import { theme as appTheme } from '../src/theme/theme'
import { createThemeFromMuiTheme } from './utils/create-theme-from-mui-theme'
addons.setConfig({
theme: createThemeFromMuiTheme({
theme: appTheme.light,
options: {
base: 'light',
brandTitle: 'Storybook with MUI',
brandUrl: 'https://www.github.com/IgorSzyporyn/storybook-with-mui'
},
})
})
然后在 preview.ts
中,您需要像这样设置 light/dark 覆盖
import React from 'react'
import { addDecorator } from '@storybook/react'
import { theme as appTheme } from '../src/theme/theme'
import { WithMuiTheme } from './components/WithMuiTheme'
import { createThemeFromMuiTheme } from './utils/create-theme-from-mui-theme'
addDecorator((story) => <WithMuiTheme>{story()}</WithMuiTheme>)
export const parameters = {
exportedParameter: 'exportedParameter',
darkMode: {
current: 'light',
light: createThemeFromMuiTheme({ theme: appTheme.light, asStorybookTheme: false }),
dark: createThemeFromMuiTheme({ theme: appTheme.dark, asStorybookTheme: false })
},
}
然后像这样制作你的装饰器包装纸./components/WithMuiThemeProps
import React from 'react'
import { MuiThemeProvider, CssBaseline, StylesProvider } from '@material-ui/core'
import { useThemeType } from '../hooks/UseThemeType'
import { theme } from '../../src/theme/theme'
type WithMuiThemeProps = {
children: React.ReactNode
}
export const WithMuiTheme = ({ children }: WithMuiThemeProps) => {
const themeType = useThemeType()
return (
<MuiThemeProvider theme={theme[themeType]}>
<CssBaseline />
<StylesProvider injectFirst>{children}</StylesProvider>
</MuiThemeProvider>
)
}
这是使更新发生的挂钩 ./hooks/UseThemeType.ts
import React from 'react'
import addons from '@storybook/addons'
const channel = addons.getChannel()
export const useThemeType = () => {
const [isDark, setDark] = React.useState(false)
React.useEffect(() => {
channel.on('DARK_MODE', setDark)
return () => channel.off('DARK_MODE', setDark)
}, [channel, setDark])
const paletteType = isDark ? 'dark' : 'light'
return paletteType
}
最后是./utils/create-theme-from-mui-theme.ts
import { create } from '@storybook/theming/create'
import { Theme } from '@material-ui/core'
type CreateThemFromMuiTheme = {
theme: Theme
options?: Object
asStorybookTheme?: boolean
}
export const createThemeFromMuiTheme = ({
theme,
options = {},
asStorybookTheme = true,
}: CreateThemFromMuiTheme) => {
const themeValue = {
colorPrimary: theme.palette.primary.main,
colorSecondary: theme.palette.secondary.main,
// UI
appBg: theme.palette.background.paper,
appContentBg: theme.palette.background.default,
appBorderColor: theme.palette.background.paper,
appBorderRadius: theme.shape.borderRadius,
// Typography
fontBase: theme.typography.fontFamily,
fontCode: 'monospace',
// Text colors
textColor: theme.palette.text.primary,
textInverseColor: theme.palette.text.secondary,
// Toolbar default and active colors
barTextColor: theme.palette.text.secondary,
barSelectedColor: theme.palette.secondary.main,
barBg: theme.palette.background.default,
// Form color
inputBg: 'transparent',
inputBorder: 'silver',
inputTextColor: theme.palette.text.primary,
inputBorderRadius: theme.shape.borderRadius,
...options,
}
return asStorybookTheme ? create(themeValue) : themeValue
}
现在您将能够使用完全集成到 Storybook 中的主题 - 当您切换 Storybook 主题时,Storybook 本身将更改为主题,您使用的组件也会更改。