【问题标题】:How to theme Material UI inside Storybook如何在 Storybook 中为 Material UI 设置主题
【发布时间】:2020-09-01 19:00:56
【问题描述】:

目前这就是我正在做的,在我的组件文件上方传递一个ThemeProvider

import React from 'react';
import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import MUIButton from '@material-ui/core/Button';

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#ff0000"
    }
  },
  typography: {
    fontFamily: 'Nunito Sans, sans-serif',
    button: {
      textTransform: 'none'
    }
  },
  shape: {
    borderRadius: 3
  }
})


export default ({ variant, children }) => {
  return (
    <ThemeProvider theme={theme}>
      <MUIButton
        color="primary"
        variant={variant}
      >
        {children}
      </MUIButton>
    </ThemeProvider>
  )
}

我正在尝试在 Storybook 中找出如何在全球范围内做到这一点。这是我构建的第一个组件,名为Button。所以我希望能够将主题放在外部文件中,并让ThemeProvider 进入更高级别,这样我就不必包装每个组件。希望这是有道理的,如果有人有任何想法。

【问题讨论】:

    标签: reactjs material-ui storybook


    【解决方案1】:

    首先,我建议您将您的主题移动到一个单独的文件中(例如src/stylesheet,以便您可以从不同的文件(您的全局App 组件和您的故事书预览文件)访问它。

    // src/stylesheet.ts
    
    import { createMuiTheme } from '@material-ui/core/styles';
    
    export const muiTheme = createMuiTheme({
      palette: {
        primary: {
          main: "#ff0000"
        }
      },
      typography: {
        fontFamily: 'Nunito Sans, sans-serif',
        button: {
          textTransform: 'none'
        }
      },
      shape: {
        borderRadius: 3
      }
    })
    

    然后,您需要像设置 React 应用一样设置 Storybook。为此,请尝试创建一个名为: .storybook/preview.js 并将其放入其中:

    // .storybook/preview.js
    
    import React from 'react';
    
    import { addDecorator } from '@storybook/react';
    import { ThemeProvider } from '@material-ui/core/styles';
    
    import { muiTheme } from '../src/stylesheet';
    
    addDecorator((story) => (
        <ThemeProvider theme={muiTheme}>{story()}</ThemeProvider>
    ));
    

    它将把你所有的故事都包含在ThemeProvider中。

    在您的应用中,您还可以拥有一个全局 App 组件,它将整个应用封装在 ThemeProvider

    更多帮助: https://storybook.js.org/docs/basics/writing-stories/

    【讨论】:

    • 对于新版本的 Storybook v6 使用类似 export const decorators = [{story()}]
    【解决方案2】:

    对于 Storybook 6.3+,它应该如下所示

    更新 preview.js 为:

    import React from 'react';
    import { theme } from './src/theme'; // whereever you have defined your material ui theme
    
    export const decorators = [
      Story => (
        <ThemeProvider theme={theme}>
          <Story />
        </ThemeProvider>
      ),
    ];
    
    

    有关如何在此处装饰您的故事的更多详细信息: https://storybook.js.org/docs/react/writing-stories/decorators

    并在此处为 Material UI 创建主题: https://material-ui.com/customization/theming/

    【讨论】:

      【解决方案3】:

      这是唯一适用于 MUI v5 的解决方案:

      // .storybook/main.js
      
      const path = require('path');
      const toPath = (filePath) => path.join(process.cwd(), filePath);
      
      module.exports = {
         webpackFinal: async (config) => {
          return {
             ...config,
            resolve: {
               ...config.resolve,
              alias: {
                ...config.resolve.alias,
                '@emotion/core': toPath('node_modules/@emotion/react'),
                'emotion-theming': toPath('node_modules/@emotion/react'),
              },
            },
          };
        },
      };
      
      
      // .storybook/preview.js
      
      import { ThemeProvider, createTheme } from '@mui/material/styles';
      import { ThemeProvider as Emotion10ThemeProvider } from 'emotion-theming';
      
      const defaultTheme = createTheme(); // or your custom theme
      
      const withThemeProvider = (Story, context) => {
        return (
          <Emotion10ThemeProvider theme={defaultTheme}>
            <ThemeProvider theme={defaultTheme}>
              <Story {...context} />
            </ThemeProvider>
          </Emotion10ThemeProvider>
        );
      };
      
      export const decorators = [withThemeProvider];
      
      // ...other storybook exports
      

      它来自 MUI 迁移指南,但我花了很长时间才找到,所以我想在这里分享它: https://mui.com/guides/migration-v4/

      【讨论】:

      • 是的,唯一有效的解决方案!谢谢!
      猜你喜欢
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2020-09-05
      • 2018-08-10
      • 2019-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多