Search code examples
reactjsmaterial-uistorybook

How to theme Material UI inside Storybook


Currently this is what I am doing, passing a ThemeProvider above my component file:

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>
  )
}

I am trying to figure out how I can do this at a global level in Storybook. This is the first component I have built out called Button. So I want to be able to have the theme in an external file, and have the ThemeProvider coming in at a higher level so I don't have to wrap each component. Hope that makes sense, and if anyone has any ideas.


Solution

  • First, I suggest you to move your theme into a separate file (such as src/stylesheet so you can access it from different files (your global App component and your storybook preview file).

    // 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
      }
    })
    

    Then, you need to setup your storybook the same way you set up your react app. To do so, try to create a file called: .storybook/preview.js and put this inside of it:

    // .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>
    ));
    

    It will wrap all your stories inside of the ThemeProvider.

    In your app, you can can also have a global App component which will encapsulate the whole app within the ThemeProvider

    More help: https://storybook.js.org/docs/basics/writing-stories/