vertexbz / storybook-addon-jss-theme

JSS theming addon for storybook.js.org
MIT License
7 stars 0 forks source link

Add support for material UI theming #1

Open StudioSpindle opened 4 years ago

StudioSpindle commented 4 years ago

Great Add-on, very useful.

There is another specific use-case I would like to hear your opinion on.

In our storybook we combine our own custom components with Material-UI components.

Now there already is a Material-UI add-on. However, this has its own events. For example when you switch between themes.

Ideally the same add-on should be used for theme switching. So the same events are re-used, for instance when you're switching between themes. ('selectTheme', 'setThemes')

What are your thoughts on making this storybook addon more agnostic?

It seems that it's almost there already, as I will explain in a following comment.

StudioSpindle commented 4 years ago

In ./src/ThemesProvider there is already a ThemeProvider which you can provide in the props.

Perhaps an additional class can be added which is based on material UI?

I am currently using a custom file in my project which is the following:

./storybook/customAddOn/MaterialUiTheme.js

import addons from "@storybook/addons";
import {createMuiTheme, MuiThemeProvider} from "@material-ui/core";
import React from "react";

export default
class MaterialUiTheme extends React.Component {
  state = {
    theme: this.props.themes[0]
  };

  constructor(...args) {
    super(...args);
    this.setTheme = this.setTheme.bind(this);
  }

  setTheme(theme) {
    this.setState({ theme });
  }

  componentDidMount() {
    const channel = addons.getChannel();
    channel.on('selectTheme', this.setTheme);
    channel.emit('setThemes', this.props.themes);
  }

  componentWillUnmount() {
    const channel = addons.getChannel();
    channel.removeListener('selectTheme', this.setTheme);
  }

  render(){
    if (!this.state.theme) {
      return null;
    }

    return (
        <MuiThemeProvider theme={createMuiTheme(this.state.theme.variables)}>
          {this.props.children}
        </MuiThemeProvider>
    );
  }
}

And am using it in the story:

import React from 'react';
import { storiesOf } from '@storybook/react';

import { withThemesProvider } from 'storybook-addon-jss-theme';
// custom add-on file:
import MaterialUiTheme from '../../.storybook/customAddOn/MaterialUiTheme';
import themes from '../theme';

import { Typography } from '@material-ui/core';

const withTheme = (cb) => (
  <MaterialUiTheme themes={themes}>{cb()}</MaterialUiTheme>
);

storiesOf('Typography', module)
    .addDecorator(withThemesProvider(themes)) // needs to be present
    .addDecorator(withTheme) // extended functionality
    .add('Example', () => {
      return (
        <>
          <Typography variant="h1" component="h2" gutterBottom>
            h1. Heading
          </Typography>
          <Typography variant="h2" gutterBottom>
            h2. Heading
          </Typography>
        </>
      )
    });

Would love to contribute to your project and am interested to hear your thoughts.