Git Product home page Git Product logo

react-theming / storybook-addon Goto Github PK

View Code? Open in Web Editor NEW
206.0 4.0 36.0 11.17 MB

Develop themable components with Emotion/Styled Components/Material-UI with help of Storybook & React Theming

Home Page: https://react-theming.github.io/storybook-addon

License: MIT License

JavaScript 95.47% HTML 4.46% Shell 0.07%
storybook react react-storybook-addons react-theme theming-boilerplate react-storybook material-ui theme addon developer-tools

storybook-addon's Introduction

npm version Storybook

Storybook Addon @ React Theming

Storybook addon for Styled Components, Emotion, Material-UI and any other theming solution. Allows to develop themed components in isolation.

npm i --save-dev @react-theming/storybook-addon

Demo

example

Features 💫

  • Universal - can be used with any styling library
  • Switching between themes from addon panel.
  • Change a color and see how it affects to your components
  • Easily copy-paste paths of nesting theme props into your code
  • Auto changes background
  • Supports dark Storybook theme
  • Keep selected theme on stories updates

Usage

specify addon in .storybook/main.js

// .storybook/main.js

module.exports = {
  stories: ['../src/**/*.stories.js'],
  addons: ['@react-theming/storybook-addon'],
};

or in .storybook/addons.js for older versions of Storybook

import '@react-theming/storybook-addon/register';

Then you'll need to add a decorator with a ThemeProvider of your library. This project is not related to any particular styling solutions, instead, you can use any of theme providers you're using in your project.

import ThemeProvider from 'library-of-your-choice';
import { withThemes } from '@react-theming/storybook-addon';
import { theme } from '../src/theme';

// create decorator
const themingDecorator = withThemes(ThemeProvider, [theme]);

ThemeProvider should accept a theme via theme props. This is usually the case for the most common styling libraries like Styled Components, Emotion, Material-UI.

In case of non standard ThemeProvider you can pass providerFn function in options:

const providerFn = ({ theme, children }) => {
  return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};

const themingDecorator = withThemes(null, [theme], { providerFn });

Use your output of the selected value

// .storybook/preview.js

import { ThemeProvider } from 'styled-components';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import { theme } from '../src/theme';

Example getCustomFieldSnippet

const selectedValue = {
  name: "accent5",
  namespace: ["palette", "colors"],
  type: "color",
  value: "#ac924d"
}


const getCustomFieldSnippet = selectedValue => {
  const { namespace, name } = selectedValue;
  const path = namespace.join('.');
  const fullPath = `${path}.${name}`;
  const themeProp = `\${({ theme }) => theme.${fullPath}}`;
  return themeProp;
};

// The snippet Func function takes the SelectedValue parameter and returns a string
addDecorator(withThemes(ThemeProvider, [theme], { getCustomFieldSnippet }));

Example getCustomValueSnippet

By default, the addon outputs colors in HEX format, if you need some kind of add-in, then pass the colorSnippet parameter.

const getCustomValueSnippet = ({value, name, type}) => {
  // Here is your code
  return value
};

// The colorSnipept function accepts an object consisting of { value : HEX, name: string, type: color}
addDecorator(withThemes(ThemeProvider, [theme], { getCustomValueSnippet }));

BACKGROUND COLOR

This addon has ability to auto change background color when it detect a dark theme. By default it checks if the theme name contains 'dark'.

You can customize this behavior by passing onThemeSwitch function:

export const onThemeSwitch = context => {
  const { theme } = context;
  const background = theme.name === 'Dark theme' ? '#2c2f33' : 'white';
  const parameters = {
    backgrounds: {
      default: background,
    },
    // Pass backgrounds: null to disable background switching at all
  };
  return {
    parameters,
  };
};

const themingDecorator = withThemes(null, [theme], { onThemeSwitch });

This way you can have own checks of what the theme is selected and pass what ever color you need.

!important: The addon change background color on each theme selecting. In some scenarios you might want to disable this behavior e.g. if you already using addon-backgrounds. You can disable background switching by passing backgrounds: null in parameters.

Below the use cases for most popular styling libraries:

Using with Emotion

// .storybook/preview.js

import { ThemeProvider } from '@emotion/react';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import { theme } from '../src/theme';

// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(ThemeProvider, [theme]));

💅 Using with Styled Components

// .storybook/preview.js

import { ThemeProvider } from 'styled-components';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import { theme } from '../src/theme';

// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(ThemeProvider, [theme]));

Using with Material-UI

// theme.js
import { red } from '@material-ui/core/colors';

// A custom theme for this app
const theme = {
  palette: {
    primary: {
      main: '#556cd6',
    },
    secondary: {
      main: '#19857b',
    },
    error: {
      main: red.A400,
    },
    background: {
      default: '#fff',
    },
  },
};

export default theme;
// .storybook/preview.js

import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import theme from '../src/theme';

const providerFn = ({ theme, children }) => {
  const muTheme = createMuiTheme(theme);
  return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};

// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(null, [theme], { providerFn }));
// index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from '@material-ui/core/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import App from './App';
import theme from './theme';

ReactDOM.render(
  <ThemeProvider theme={createMuiTheme(theme)}>
    <App />
  </ThemeProvider>,
  document.querySelector('#root'),
);

There is an example app with CRA, Material-UI and Storybook Addon Demo Source

Credits

Created with ❤︎ to React and Storybook by Oleg Proskurin [React Theming]

storybook-addon's People

Contributors

aashnisshah avatar alexandrlitkevich avatar averethel avatar b3nb5n avatar chasesinclair avatar coderkevin avatar cwsites avatar dependabot[bot] avatar helltux avatar hmelenok avatar hoschi avatar hyeinu avatar jhedlund79 avatar joshjconlin avatar leewarnock avatar luckey007 avatar m-m-0-0 avatar marie-donnie avatar maryna-yanul avatar milesibastos avatar minibhati93 avatar mzamoras avatar radhikadua123 avatar sanketmaru avatar shilman avatar siiiiilvio avatar thatbraxguy avatar thisislawatts avatar usulpro avatar xrahul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

storybook-addon's Issues

Only one theme is displaying at a time.

Hi, greatly appreciate you creating this add-on.

I encountered a bug. As in, I have three themes in folder '../src/themes' and only one of my them is displaying. Any idea why that might be the case?

Here is the code I added to config.js:

import { ThemeProvider } from '../src/index';
import { withThemes } from '@react-theming/storybook-addon';
import theme from '../src/theme'; (There are 3 theme JS files in this folder.)

const themingDecorator = withThemes(ThemeProvider, [theme]);
addDecorator(themingDecorator);

Also, when I click on the theme nothing changes. May I know why that's the case? I believe I have followed your instructions properly.

Oh, I'm still using an older version of Storybook (version 5.2.6).

Kindly assist.
Screenshot 2021-06-23 at 11 01 26 AM

Theme switches when I switch component variant

Hi there,

I'm running into an issue with the theme switching whenever I click on a different variant. I have primary, secondary and tertiary variants for my button component. For example, when I select a different theme and click on secondary, it ends up selecting the first theme in the array and applies the styles for the secondary button for that theme.

I noticed in your demo when I select Light Theme 2, I'm able to click on Buttons 1, 2 and 3 and see the theme apply to all the variants and it stays on the selected theme.

Attached is a gif.

2022-07-18 14 34 10

Using alpha version of Storybook

Sorry to bother, I'm using @storybook/*@6.5.0-alpha.36 because of some emotion issues I was having. So far everything is working and I can use it locally but when I run install on my pipelines I get the following error.

$ npm i
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! 
npm ERR! While resolving: @react-theming/[email protected]
npm ERR! Found: @storybook/[email protected]
npm ERR! node_modules/@storybook/react
npm ERR!   dev @storybook/react@"^6.5.0-alpha.36" from the root project
npm ERR!   peer @storybook/react@"*" from @storybook/[email protected]
npm ERR!   node_modules/@storybook/addon-devkit
npm ERR!     @storybook/addon-devkit@"^1.4.2" from @react-theming/[email protected]
npm ERR!     node_modules/@react-theming/storybook-addon
npm ERR!       dev @react-theming/storybook-addon@"^1.1.5" from the root project
npm ERR!   1 more (@storybook/addon-docs)
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer @storybook/react@"^5.0.0 || ^6.0.0" from @react-theming/[email protected]
npm ERR! node_modules/@react-theming/storybook-addon
npm ERR!   dev @react-theming/storybook-addon@"^1.1.5" from the root project
npm ERR! 
npm ERR! Conflicting peer dependency: @storybook/[email protected]
npm ERR! node_modules/@storybook/react
npm ERR!   peer @storybook/react@"^5.0.0 || ^6.0.0" from @react-theming/[email protected]
npm ERR!   node_modules/@react-theming/storybook-addon
npm ERR!     dev @react-theming/storybook-addon@"^1.1.5" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See /root/.npm/eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-05-03T23_00_20_503Z-debug-0.log
Cleaning up project directory and file based variables 00:01
ERROR: Job failed: command terminated with exit code 1

I don't really know how to address this. Any tip?

Support for `window.matchMedia('(prefers-color-scheme: dark)')`

I am using Emotion Styled Components.
Firstly, everything works as expected. However...

Problem

But recently I added a way for the theme to detect color-scheme of the OS and make the switch to dark or light as the user switches color scheme in the OS. However the theme radio button of this addon doesn't switch. The problem is this non-synergy between the underlying theme change and the addon.

What I expect?

I expect the addon to accomodate this and sync accordingly. I'll have to read through your code and see if I can do a pull request. But this shouldn't be too hard to implement. Please implement this or provide an option to manually through code implement this while storybook is running as this color scheme detection requires the window object of the browser.

Registering addon in addons.js - Modules not found

I don't know if I'm doing something wrong, but simply registering this addon in my addons.js file breaks my storybook build. I followed all of the other directions in the README but it doesn't matter since it cannot even register the addon.

Does this only support the newer storybook config way?

addons.js
import '@react-theming/storybook-addon/register';

ERROR in ./node_modules/@storybook/addon-devkit/dist/store/store.js
Module not found: Error: Can't resolve 'immutable' in 'C:\Users\username\Documents\formation-ui\node_modules@storybook\addon-devkit\dist\store'
@ ./node_modules/@storybook/addon-devkit/dist/store/store.js 18:17-37
@ ./node_modules/@storybook/addon-devkit/dist/index.js
@ ./node_modules/@react-theming/storybook-addon/dist/manager/register.js
@ ./node_modules/@react-theming/storybook-addon/register.js
@ ./.storybook/addons.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/client/manager/index.js ./.storybook/addons.js ./node_modules/@storybook/addon-docs/dist/register.js

ERROR in ./node_modules/@storybook/addon-devkit/dist/store/store.js
Module not found: Error: Can't resolve 'podda' in 'C:\Users\username\Documents\formation-ui\node_modules@storybook\addon-devkit\dist\store'
@ ./node_modules/@storybook/addon-devkit/dist/store/store.js 28:13-29
@ ./node_modules/@storybook/addon-devkit/dist/index.js
@ ./node_modules/@react-theming/storybook-addon/dist/manager/register.js
@ ./node_modules/@react-theming/storybook-addon/register.js
@ ./.storybook/addons.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/client/manager/index.js ./.storybook/addons.js ./node_modules/@storybook/addon-docs/dist/register.js

ERROR in ./node_modules/@storybook/addon-devkit/dist/store/store.js
Module not found: Error: Can't resolve 'react-komposer' in 'C:\Users\username\Documents\formation-ui\node_modules@storybook\addon-devkit\dist\store'
@ ./node_modules/@storybook/addon-devkit/dist/store/store.js 26:21-46
@ ./node_modules/@storybook/addon-devkit/dist/index.js
@ ./node_modules/@react-theming/storybook-addon/dist/manager/register.js
@ ./node_modules/@react-theming/storybook-addon/register.js
@ ./.storybook/addons.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/client/manager/index.js ./.storybook/addons.js ./node_modules/@storybook/addon-docs/dist/register.js

package.json
"peerDependencies": { "react": "^16.12.0", "react-dom": "^16.12.0" }, ... "devDependencies": { "@react-theming/storybook-addon": "^1.0.0", ... "@storybook/react": "^5.3.14", ...

Material UI v5.0 Theme is not applied

Hi,
I'm trying to use this addon with React Material-UI v5.0 (currently next)
I've configured all my storybook as mentioned in the doc but the template seems not to be applied.
I know v5 is not the current stable, and has breaking changes (location of Theme related functions) with the current version but it seemed to me that it could be working if I imported them well.

Here's what I did:

// main.js
 "addons": [
    "@react-theming/storybook-addon",
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app"
  ]

// preview.js
import { ThemeProvider, createTheme } from '@material-ui/core';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';
import { red } from '@material-ui/core/colors';

const theme = {
  palette: {
    primary: {
      main: red[50],
    }
  }
}

const providerFn = ({ theme, children }) => {
  const muTheme = createTheme(theme);
  return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};
// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(null, [theme], { providerFn }));

// Button.stories.tsx
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Button } from '@material-ui/core';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    color: {
      options: ['primary', 'secondary'],
      control: { type: 'radio' }
    }
  }
} as ComponentMeta<typeof Button>;

const Template: ComponentStory<typeof Button> = (args) => (
  <Button {...args}>
    Button
  </Button>
);

export const Primary = Template.bind({});
Primary.args = {
  color: 'primary',
  variant: 'contained'
};

And inside Storybook, the Button is showing the classic Blue from default Theme.

I'm using TS, could this be the issue ? Or maybe I missed something else?
Thx for your support.

Nota: If this can help, I have an error in the console, meaning, everything did not go well:

Warning: React does not recognize the originalStoryFn prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase originalstoryfn instead. If you accidentally passed it from a parent component, remove it from the DOM element.
at button
at MuiButtonBase-root
at ButtonBase (http://localhost:5006/vendors~main.iframe.bundle.js:4928:94)

Story keeps remounting when changes to controls are made

Using a standard theming decorator like this

export const decorators = [Story => <ThemeProvider>{Story()}</ThemeProvider>];

gives me this https://gyazo.com/a421d82700afba97fa9a0b6b66e72612

However, using the recommended approach

const themingDecorator = withThemes(ThemeProvider, [theme]);
export const decorators = [themingDecorator];

causes the component to continually remount whenever a change to the controls is made

https://gyazo.com/032167887ca9c9d872a1ef19aaa20896

Function in theme break CSS properties

Hello there! 👋
I have a couple of functions in my theme and since installing this addon they unfortunately do not work within the Storybook context. My guess is that the addon can't handle functions and they are therefore not executed, in the end resulting in the CSS properties using the functions to be removed.
As example, one of my functions is theme.spacing() that is used to calculate values for paddings, margins etc but those CSS properties are no longer generated.

An example is my Button component that lack a gap property, resulting in no space between the text and arrow icon:
Screenshot 2022-02-09 at 14 43 01

// Some of the button styles
const buttonWithIcon = (theme: Theme) => css`
    display: grid;
    grid-auto-flow: column;
    gap: ${theme.spacing(2)}; // Works just fine then the addon isn't active
    justify-content: space-between;
    align-items: center;
// Simplified theme
const theme = {
  ...someProperties,
  spacing(factor) { return `${factor * 4}px` }
}
// preview.js in SB
const providerFn = ({ theme, children }) => (
    <ThemeProvider theme={theme}>
        {children}
    </ThemeProvider>
);

export const decorators = [withThemes(null, [{ name: "Default theme", ...defaultTheme }], { providerFn })];

I'm using SB 6.5 (still in alpha release), Emotion 11 and v1.1.5 of this addon.
I've tried to create a Codesandbox but not yet succeeded, will try to get back to you with one.

Chromatic support?

Using this library / tool, how would we auto-switch snapshots for Chromatic to take a snapshot per story per theme?

Note, after a lot of debugging with the Chromatic team, and build snapshots failing over and over, we narrowed it down to this particular library. Note that this fails Chromatic builds / verification! I don't know why, and they couldn't produce errors that explained it.

Dependencies out of date

Please use an updated version of @usulpro/react-json-view everywhere. When it's not specified it pulls in an older version which has an older version of [email protected] which is referencing an outdated version of react.

Notice the top two have an updated version of [email protected] but the third one does not.

warning "@react-theming/storybook-addon > @usulpro/[email protected]" has incorrect peer dependency "react@^16.0.0 || ^15.5.4".
warning "@react-theming/storybook-addon > @usulpro/[email protected]" has incorrect peer dependency "react-dom@^16.0.0 || ^15.5.4".
warning "@react-theming/storybook-addon > @usulpro/react-json-view > [email protected]" has incorrect peer dependency "react@>=0.14.0 <17.0.0".

Plugin not working after upgrade to v1.1.2

We have been using react-theming/storybook-addon for quite some time and it was working fine. After recent upgrade to v1.1.2, the plugin is not working and we are seeing theming tab with 'Waiting for data' message. Also, below console error is seen when we click on the theming tab.

vendorsmain.801c64baa44ce1fed39c.manager.bundle.js:16 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'setQueryParams')
at setCurrent (vendors
main.801c64baa44ce1fed39c.manager.bundle.js:16)
at vendorsmain.801c64baa44ce1fed39c.manager.bundle.js:16
at vendors
main.801c64baa44ce1fed39c.manager.bundle.js:16
at fk (vendorsmain.801c64baa44ce1fed39c.manager.bundle.js:16)
at exports.unstable_runWithPriority (vendors
main.801c64baa44ce1fed39c.manager.bundle.js:16)
at gg (vendorsmain.801c64baa44ce1fed39c.manager.bundle.js:16)
at Oj (vendors
main.801c64baa44ce1fed39c.manager.bundle.js:16)
at Lj (vendorsmain.801c64baa44ce1fed39c.manager.bundle.js:16)
at vendors
main.801c64baa44ce1fed39c.manager.bundle.js:16
at exports.unstable_runWithPriority (vendors~main.801c64baa44ce1fed39c.manager.bundle.js:16)

This error seems to be related to the changes made in commit 8f9a3ca.

Could you please suggest if we have to make any changes in the addon usage after the recent upgrade?

Support react 18

Hello, we use the addon in storybook with chakra-ui.
In their most recent release, they switched to react 18.

Would it be possible to relax the peer dependency requirements on react version or does it require some more work on the addon internals?
I'd be happy to support here if it's more complex than just adding another version to peer deps too.

How to install?

Hello, I tried to install via npm i --save-dev @react-theming/storybook-addon and I get the following error

Screen Shot 2022-03-28 at 3 42 03 PM

It looks like some progress has been made towards this issue (#14), so I thought maybe the fixes hadn't been published, so I tried npm i react-theming/storybook-addon to install from master, but I get the same error.

How can I install this?

Theming option tab not showing

Was the theming option removed recently? Im having the same issue as #28

My setup looks like this:

import { createTheme, ThemeProvider } from '@material-ui/core';
import { withThemes  } from '@react-theming/storybook-addon';
import themes from '../src/themes';

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

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};


// A custom theme for this app
const theme = {
  palette: {
    primary: {
      main: '#556cd6',
    },
    secondary: {
      main: '#19857b',
    },
    error: {
      main: red.A400,
    },
    background: {
      default: '#fff',
    },
  },
};

const providerFn = ({ theme, children }) => {
  const muiTheme = createTheme(theme);
  return (
    <ThemeProvider theme={muiTheme}>{children}</ThemeProvider>
  );
};

const themingDecorator = withThemes(null, [ themes.new, theme ], { providerFn });

export const decorators = [
  themingDecorator,
];

ReferenceError: htmlFontSize is not defined

"@react-theming/storybook-addon": "^1.1.1"

I'm trying to use this addon with material UI

this how I use it:

preview.ts

import { withThemes } from "@react-theming/storybook-addon";
import { lightTheme, defaultTheme } from "../src/ThemeKnobs";
import { providerFn } from "./providerFn";

export const decorators = [
  withThemes(null, [lightTheme, defaultTheme], { providerFn: providerFn }),
];

providerFn.tsx

import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";

export const providerFn = ({ theme, children }) => {
  return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>;
};

And I'm passing theme that already wrapped by createMuiTheme

but instead I got this following error in storybook:

ReferenceError: htmlFontSize is not defined
    at eval (eval at result (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:192143:17), <anonymous>:1:43)
    at Object.pxToRem (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:192144:18)
    at styles (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:4782:34)
    at Object.create (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:25938:35)
    at attach (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:26378:32)
    at http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:26520:7
    at useSynchronousEffect (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:26472:14)
    at useStyles (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:26512:5)
    at WithStyles (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:27004:21)
    at renderWithHooks (http://localhost:6007/vendors~main.a885dca276ee58d36a58.bundle.js:164060:18)

Also there is no difference result between using themeprovider from "@material-ui/core" and "@material-ui/core/styles"

and write it like this like in the docs is also produce the same result


  withThemes(null, [lightTheme, defaultTheme], { providerFn })

MaterialUI implementation not working

Not sure if the docs are out of date, but I'm trying to implement this plugin for MaterialUI

Using with Material-UI

// theme.js
import { red } from '@material-ui/core/colors';

// A custom theme for this app
const theme = {
  palette: {
    primary: {
      main: '#556cd6',
    },
    secondary: {
      main: '#19857b',
    },
    error: {
      main: red.A400,
    },
    background: {
      default: '#fff',
    },
  },
};

export default theme;
// .storybook/preview.js

import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import theme from '../src/theme';

const providerFn = ({ theme, children }) => {
  const muTheme = createMuiTheme(theme);
  return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};

// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(null, [theme]));
// index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { ThemeProvider } from '@material-ui/core/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import App from './App';
import theme from './theme';

ReactDOM.render(
  <ThemeProvider theme={createMuiTheme(theme)}>
    <App />
  </ThemeProvider>,
  document.querySelector('#root'),
);

Although the above example doesn't even seem to reference providerFn, I tried to use the following

// preview.js

import { withThemes } from '@react-theming/storybook-addon';
import { withThemeProvider } from './decorators';
import { theme } from '../src/styles/theme';

addDecorator(withThemes(null, [theme], { withThemeProvider }));
// decorators.js

import { MuiThemeProvider} from '@material-ui/core';
import { theme } from '../src/styles/theme';

export const withThemeProvider = ({ children }) => {
  return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>;
}

and I get the following error in storybook

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: null.
    at createFiberFromTypeAndProps (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:204846:21)
    at createFiberFromElement (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:204874:15)
    at reconcileSingleElement (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:193845:23)
    at reconcileChildFibers (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:193905:35)
    at reconcileChildren (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:196783:28)
    at mountIndeterminateComponent (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:197683:5)
    at beginWork (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:198842:16)
    at HTMLUnknownElement.callCallback (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:183738:14)
    at Object.invokeGuardedCallbackDev (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:183787:16)
    at invokeGuardedCallback (http://localhost:4400/vendors~main.552165771ec047452ec4.bundle.js:183849:31)

White screen after adding the addon

Hello, first of all thanks for this addon, it looks exactly what i need!

I'm getting an error when adding this addon to a brand new storybook, with a single component, styled with styled-components.

The builds compiles succesfully, but then opening the url doesn't show anything, and the console prints out this error:

Uncaught undefined
VM24:37 The above error occurred in one of your React components:
    in Unknown (created by Scroller)
    in Suspense (created by Scroller)
    in Scroller (created by Context.Consumer)
    in Styled(Scroller)
    in Unknown (created by Context.Consumer)
    in Bar (created by FlexBar)
    in FlexBar (created by Tabs)
    in div (created by Context.Consumer)
    in Styled(div) (created by Tabs)
    in Tabs
    in Tabs (created by AddonPanel)
    in AddonPanel
    in Unknown (created by ManagerConsumer)
    in ManagerConsumer (created by Panel)
    in Panel (created by Layout)
    in div (created by Context.Consumer)
    in Styled(div) (created by Panel)
    in Panel (created by Layout)
    in div (created by Context.Consumer)
    in Styled(div) (created by Main)
    in div (created by Context.Consumer)
    in Styled(div) (created by Main)
    in Main (created by Layout)
    in Layout (created by Context.Consumer)
    in WithTheme(Layout) (created by DesktopLayout)
    in DesktopLayout (created by App)
    in div (created by Context.Consumer)
    in Styled(div) (created by App)
    in App
    in App (created by SizeMeRenderer(Component))
    in SizeMeReferenceWrapper (created by SizeMeRenderer(Component))
    in SizeMeRenderer(Component) (created by SizeMe(Component))
    in SizeMe(Component)
    in ThemeProvider
    in Unknown (created by ManagerConsumer)
    in ManagerConsumer (created by Manager)
    in EffectOnMount (created by Manager)
    in Manager (created by Context.Consumer)
    in Location (created by QueryLocation)
    in QueryLocation (created by Root)
    in LocationProvider (created by Root)
    in HelmetProvider (created by Root)
    in Root

React will try to recreate this component tree from scratch using the error boundary you provided, LocationProvider.
window.console.error @ VM24:37
vendors~main.manager.bundle.js:3645 Uncaught undefined
VM24:37 The above error occurred in the <LocationProvider> component:
    in LocationProvider (created by Root)
    in HelmetProvider (created by Root)
    in Root

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
window.console.error @ VM24:37
vendors~main.manager.bundle.js:113186 Uncaught undefined
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)
:6006/runtime-error:1 Failed to load resource: the server responded with a status of 404 (Not Found)

Any guess of how to fix that?

I'm currently using

    "@babel/core": "^7.13.14",
    "@react-theming/storybook-addon": "^1.1.1",
    "@storybook/addon-actions": "^6.2.3",
    "@storybook/addon-essentials": "^6.2.3",
    "@storybook/addon-links": "^6.2.3",
    "@storybook/react": "^6.2.3",
    "babel-loader": "^8.2.2",
    "sass-loader": "^10.1.1"
    "react": "^17.0.1"
    "styled-components": "^5.2.3",

And these are my config files:

// main.js
const path = require("path");

module.exports = {
  stories: ["../src/**/*.stories.tsx"],
  addons: [
    "@react-theming/storybook-addon",
    "@storybook/addon-links",
    "@storybook/addon-essentials",
  ],
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ["style-loader", "css-loader", "sass-loader"],
      include: [path.resolve(__dirname, "../")],
    });
    return config;
  },
};
// preview.js
import { ThemeProvider } from "styled-components";
import { addDecorator } from "@storybook/react";
import { withThemes } from "@react-theming/storybook-addon";

import { myTheme } from "../src";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

addDecorator(withThemes(ThemeProvider, [myTheme]));

Storybook's "dark" theme support

Hi there,

First of all, thanks for the nice addon! I'm using Storybook's built-in "dark" theme, and it looks like the addon doesn't fully support it:

Screen Shot 2021-01-24 at 4 54 13 PM

// .storybook/manager.js

import { addons } from "@storybook/addons";
import { themes } from "@storybook/theming";

addons.setConfig({
    theme: themes.dark,
});

Please let me know if you'd prefer a PR instead of a bug submit :)

Flash of "no theme"

Hi,

Whenever a story renders, I'm seeing a flash of "no theme" for a split-second before it works.

This is just a small annoyance in normal use, but Chromatic seems to screenshot the "no theme", so it breaks that facility completely.

I've tracked it down to src/preview/index.js, occurring when isFirstDataReceived is falsey, which comes from @storybook/addon-devkit. I don't know where to go from there.

This is with:

  • @storybook/react v5.3.19
  • @react-theming/storybook-addon v1.0.2
  • @storybook/addon-devkit v1.3.7
  • @material-ui/core v4.11.0

and calling

const themeProvider = ({theme, children}) => (
    <MuiThemeProvider theme={createMuiTheme(theme)}>
        {children}
    </MuiThemeProvider>
);
addDecorator(withThemes(themeProvider, [themeData]))

in .storybook/preview.js

I suppose this could be a similar problem to that in #3, considering the indication of "no theme".

Improvement: Let people name their themes

Not sure if this is already possible somehow, but I did not find anything yet. I love the addon, but we are using storybook and MUI to change between dozens of themes for our central UI library. It would be really helpful to name them.

Using with EmotionJS

@usulpro sorry to pester but this seems like a real issue and being that I can't reproduce it in the actual repo I am not sure how to assist or proceed.

I have created a separate repo that demonstrates the issue. This example repo was create with create-react-app and sb init. I then added a button example using the same code as used in the addons demo code.

https://github.com/dptoot/react-theming-storybook-addon-test

npm run storybook will show the error occurring with [email protected] when the button story is selected

RangeError
Maximum call stack size exceeded

Pinning the all storybook dependencies to v6.3.12 will show the addon to work as expected.

Hopefully this is helpful

Originally posted by @dptoot in #39 (comment)

console.log msg `onThemeSwitch was not supported`

Everything works fine, but in console output I see msg that onThemeSwitch was not supported :( !

My preview.js

import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';
import { ThemeProvider } from '@emotion/react'
import * as NextImage from "next/image";
import "../styles/globals.css";

const OriginalNextImage = NextImage.default;

Object.defineProperty(NextImage, "default", {
  configurable: true,
  value: (props) => <OriginalNextImage {...props} unoptimized />,
});

const themes = [
  {
    name: "dark",
    palette: {
        primary: {
            light: "#683abb",
            main: "#0a8997",
            dark: "#292b2c",
            contrastText: "#fff"
        },
        secondary: {
            light: "#c930c8",
            main: "#cbcb35",
            dark: "#192e72",
            contrastText: "#fff"
        },
        text: {
            secondary: '#fcfcfc'
        }
    },
    colors: {
        white: "#4b00dc",
        whiteTransparent: "rgba(255, 255, 255, 0.5)",
        blackTransparent: "#fcfcfc",
        accent1: "#3bd9d6",
        accent2: "#0a8997",
        accent3: "#292b2c",
        accent4: "#7c0435",
        accent5: "#ac924d",
        accent6: "#e0a8b4",
        accent7: "#6cb09e",
        accent8: "#8b8b6b",
        accent9: "#1f595f"
    },
    fontSizes: {
        small: "1em",
        medium: "2em",
        large: "3em"
    },
    text: {
        textTransform: "uppercase"
    }
  }
]

export const onThemeSwitch = ({ theme }) => ({
  backgrounds: {
    default: theme.name,
  },
})

addDecorator(withThemes(ThemeProvider, themes, { onThemeSwitch }));

export const parameters = {
  backgrounds: {
    default: "dark",
      values: [
        { name: "dark", value: "#5e5c64" },
        { name: "white", value: "#ffffff" },
      ]
  },
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

incorrect peer dependencies - React 17 Support

Running my e2e tests using cypress I get the following warnings in my CLI. I'm on v1.1.1. Is there any way to fix these? It's really annoying to see a ton of warnings.

warning " > @react-theming/[email protected]" has unmet peer dependency "@storybook/theming@^5.0.0 || ^6.0.0".
warning "@react-theming/storybook-addon > @storybook/[email protected]" has unmet peer dependency "@storybook/addons@^5.0.0".
warning "@react-theming/storybook-addon > @storybook/[email protected]" has incorrect peer dependency "@storybook/react@^5.0.0".
warning "@react-theming/storybook-addon > @storybook/[email protected]" has incorrect peer dependency "react@^16.0.0".
warning "@react-theming/storybook-addon > @storybook/[email protected]" has incorrect peer dependency "react-dom@^16.0.0".
warning "@react-theming/storybook-addon > @usulpro/[email protected]" has incorrect peer dependency "react@^16.0.0 || ^15.5.4".
warning "@react-theming/storybook-addon > @usulpro/[email protected]" has incorrect peer dependency "react-dom@^16.0.0 || ^15.5.4".
warning "@react-theming/storybook-addon > @storybook/addon-devkit > @reach/[email protected]" has incorrect peer dependency "react@^16.8.0".
warning "@react-theming/storybook-addon > @storybook/addon-devkit > @reach/[email protected]" has incorrect peer dependency "react-dom@^16.8.0".
warning "@react-theming/storybook-addon > @usulpro/react-json-view > [email protected]" has incorrect peer dependency "react@>=0.14.0 <17.0.0".
warning "@react-theming/storybook-addon > @storybook/addon-devkit > @reach/rect > @reach/[email protected]" has incorrect peer dependency "react@^16.4.0".
warning "@react-theming/storybook-addon > @storybook/addon-devkit > @reach/rect > @reach/[email protected]" has incorrect peer dependency "react-dom@^16.4.0".
warning "@react-theming/storybook-addon > @storybook/addon-devkit > @storybook/addons > @storybook/api > @reach/router > [email protected]" has incorrect peer dependency "react@^0.14.0 || ^15.0.0 || ^16.0.0".

not working with storybook 6.4

Storybook 6.4 is deprecating things like addDecorator functions.

This is such a good plug in and I have no idea how to fix it :(

it looks like this now in the preview.js file:

export const decorators = [
  (Story) => (
    <ThemeProvider theme="default">
      <Story />
    </ThemeProvider>
  ),
];

The tab for this add on with the theme inspector would still be broken :

Screenshot 2021-12-01 at 19 27 06

I ended up making my own theme switcher that lives on every story:

import { addons } from "@storybook/addons";
import { UPDATE_GLOBALS } from "@storybook/core-events";

export const decorators = [
  (Story, { globals }) => {
    const channel = addons.getChannel();

    const themeFile = (theme) => {
      switch (theme) {
        case "su2c":
          return su2cTheme;
        default:
          return crukTheme;
      }
    };

    const setTheme = (theme) => {
      channel.emit(UPDATE_GLOBALS, {
        globals: { theme },
      });
    };

    return (
      <ThemeProvider theme={themeFile(globals.theme)}>
        <Box marginBottom="m">
          <Select
            value={globals.theme}
            label="Theme"
            name="themeSelector"
            onChange={(e) => {
              setTheme(e.target.value);
            }}
          >
            <option value="cruk">CRUK theme</option>
            <option value="su2c">SU2C theme</option>
          </Select>
        </Box>
        <GlobalStyle />
        <Story />
      </ThemeProvider>
    );
  },
];

getColorSnippet is undefined in v1.1.8

CI tests are currently failing with the same issue. I'm seeing this error after updating to 1.1.8

vendors~main.manager.bundle.js:31908 Uncaught ReferenceError: getColorSnippet is not defined

Not working when opening a story in a new tab

Hi,

I'm having an issue with your addon when I do this:

  1. Open any story.
  2. Click on "open in new tab".

It justs renders "no theme" in the new tab.

It works fine when using inside the Storybook UI (Canvas + Docs tabs), although I have an annoying warning.

For info, I'm using these versions (+ emotion):

{
    "@react-theming/storybook-addon": "^1.0.2",
    "@storybook/addon-actions": "^5.3.14",
    "@storybook/addon-docs": "^5.3.14",
    "@storybook/addon-knobs": "^5.3.14",
    "@storybook/addon-viewport": "^5.3.14",
    "@storybook/addons": "^5.3.14",
    "@storybook/react": "^5.3.14",
    "@storybook/theming": "^5.3.14",
}

And using it like this

import { ThemeProvider } from 'emotion-theming';
import { withThemes } from '@react-theming/storybook-addon';

// Emotion theming.
const loadThemes = () => {
  const req = require.context('../src/config/style/themes/', true, /\.jsx?$/i);
  return req.keys().map(filename => pick(req(filename), ['name', 'theme']));
};

const themes = loadThemes();

addDecorator(
  withThemes(
    // I need to pass the themes to withThemes as { theme: {}, name: string },
    // but I only want to pass the theme to my ThemeProvider, so this is just a proxy component.
    ({ theme: { theme }, ...props }) => (
      <ThemeProvider
        {...props}
        theme={theme}
      />
    ),
    themes,
  ),
);

Error when using a material ui theme where a default prop is overwritten with a component

Defining components as default props in a material ui theme throws the following error:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
    at createFiberFromTypeAndProps (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:253875:21)
    at createFiberFromElement (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:253898:15)
    at createChild (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:243538:28)
    at reconcileChildrenArray (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:243810:25)
    at reconcileChildFibers (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:244215:14)
    at reconcileChildren (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:246672:28)
    at updateHostComponent (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:247212:3)
    at beginWork (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:248537:14)
    at HTMLUnknownElement.callCallback (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:230098:14)
    at Object.invokeGuardedCallbackDev (http://localhost:9009/vendors~main.e20e507f310929fd7c90.bundle.js:230147:16)

This error can be reproduced in the demo app (https://github.com/react-theming/theming-material-ui) by extending the example theme like this:

export const theme1 = createMuiTheme({
  // ...
  props:{
    MuiCheckbox:{
      icon:<CheckCircle/>
    }
  }
});

This error happens both with material ui v4 and v5.

node-fetch dependency vulnerabilities

Hi there! 👋

Would it be possible to patch the node-fetch vulnerabilities and version a new release? It's just a low-severity denial of service warning... but a clean console is always nice! 😄 I can raise a PR if that helps?

image

Issue with nearest-color dependency (value is not defined)

Using the Material-UI theme and everything appears to match up to documentation but seeing an issue with a dependency of react-theming for nearest-color. The storybook add-on appears to load properly, however, all stories now briefly render and immediately display a value is not defined error.


preview.js

import { ThemeProvider } from '@material-ui/core';
import { createMuiTheme } from '@material-ui/core/styles';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';

import theme from '../src/styles/theme';

const providerFn = ({ theme, children }) => {
	const muTheme = createMuiTheme(theme);
	return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};

// pass ThemeProvider and array of your themes to decorator
addDecorator(withThemes(null, [theme], { providerFn }));

export const parameters = {
	actions: { argTypesRegex: '^on[A-Z].*' },
};

main.js

module.exports = {
	stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
	addons: [
		'@storybook/addon-links',
		'@storybook/addon-essentials',
		'@react-theming/storybook-addon',
	],
};


Here is a screenshot where you can see the add-on working and reading the theme. The storybook will briefly load component rendered and then will hit me with this error screen.
image


Here is a the code in question
image

Looked like this (react-theming) storybook add-on was recommended over this one...but after swapping this morning cant seem to find what the closet color thing is doing. Not sure why I need a theme name or if its trying to auto generate me one...or if I can set programmatically and avoid the nearest color business

  • Storybook version: 6.1.21
  • React version: 16.14.0
  • Material version: 4.11.0
  • React-theming
  • React-theming storybook verion: 1.1.1

Getting error on the last version 1.0.3 colorManipulator is not defined

Hii,

After installing this plugins, on version ^1.0.3 I get the following error:

Screenshot 2021-02-12 at 18 02 21

Any way of solving this ?

Im using the following versions:

"@react-theming/storybook-addon": "^1.0.3",
"@storybook/addon-a11y": "^6.1.17",
"@storybook/addon-essentials": "^6.1.17",
"@storybook/react": "^6.1.17",

Unexpected re-render on blur

Hello! First of all thank you for this awesome addon.

I'm using it with Storybook 6 and Emotion 11 and just by adding the withThemes decorator I noticed the story re-renders on blur. This is problematic for developing because it re-renders when you open the devtools for example.

Transitions are not working using MUI 5 on Storybook (6.4.17)

I am trying to test a component, an AppBar with a User Menu Menu. I suspect that the issue is related to theming MUI5 that is using Emotion 11. The issue does not happen running on NextJS (production and development).

The error is triggered only on Storybook when I want to press a MenuItem (dropdown with transition) the following exception is triggered:


  missing } after function body

  result@http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js:116272:17
  ./node_modules/@mui/material/Grow/Grow.js/Grow/handleEnter<@http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js:9225:36
  ./node_modules/@mui/material/Grow/Grow.js/Grow/normalizedTransitionCallback/<@http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js:9202:17

But if I change main.js setting features: { emotionAlias: false }, it triggers:

  transform is not defined
  
  @http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js line 116912 > eval:1:264
  @http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js line 116912 > eval:1:232
  result@http://localhost:6006/vendors-node_modules_mui_icons-material_AccountCircle_js-node_modules_mui_icons-material_Busi-48779a.iframe.bundle.js:116913:18
  closedMixin@http://localhost:6006/main.iframe.bundle.js:705:28
  ./src/features/commons/components/AppBar.js/Drawer<@http://localhost:6006/main.iframe.bundle.js:756:34

My preview.js file:

      import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles'
      import CssBaseline from '@mui/material/CssBaseline'
      import { withThemes } from '@react-theming/storybook-addon'
      import { RouterContext } from 'next/dist/shared/lib/router-context' // next 11.1
      import { ToastProvider } from 'react-toast-notifications'
      import * as nextImage from 'next/image'
      import 'dayjs'
      import 'dayjs/locale/en'
      import 'dayjs/locale/es'
      
      import {
        LocaleProviderMock
      } from '../src/features/commons/__mocks__/hooks/useTranslationMock'
      
      import commonEs from '../public/locales/es/common.json'
      import loginEs from '../public/locales/es/login.json'
      import dashboardEs from '../public/locales/es/dashboard.json'
      import contractEs from '../public/locales/es/contract.json'
      import eventEs from '../public/locales/es/event.json'
      import languageSwitcherEs from '../public/locales/es/languageSwitcher.json'
      import usersEs from '../public/locales/es/users.json'
      import organizationsEs from '../public/locales/es/organizations.json'
      
      import theme from '../src/theme'
      import '../styles/globals.css'
      import 'nprogress/nprogress.css'
      
      const locale = Object.freeze({
        common: commonEs,
        login: loginEs,
        dashboard: dashboardEs,
        contract: contractEs,
        event: eventEs,
        languageSwitcher: languageSwitcherEs,
        users: usersEs,
        organizations: organizationsEs
      })
      
      const CThemeProvider = ({ children, theme }) => (
        <StyledEngineProvider injectFirst>
          <ThemeProvider theme={theme}>
            <ToastProvider autoDismissTimeout={7000} autoDismiss placement='bottom-right'>
              <LocaleProviderMock locale={locale}>
                <CssBaseline />
                {children}
              </LocaleProviderMock>
            </ToastProvider>
          </ThemeProvider>
        </StyledEngineProvider>
      )
      
      Object.defineProperty(nextImage, 'default', {
        configurable: true,
        value: props => {
          return (
            <div
              style={{
                position: 'relative'
              }}
            >
              <img
                style={{
                  objectFit: 'cover',
                  minWidth: '100%',
                  minHeight: '100%',
                  maxWidth: '100%',
                  maxHeight: '100%'
                }}
                {...props}
              />
            </div>
          )
        },
      })
      
      export const decorators = [
        withThemes(CThemeProvider, [theme])
      ]
      
      export const parameters = {
        nextRouter: {
          Provider: RouterContext.Provider,
          path: '/', // defaults to `/`
          asPath: '/', // defaults to `/`
          query: {}, // defaults to `{}`
          push() {
          } // defaults to using addon actions integration,
          //   can override any method in the router
        }
      }

My main.js file:

  const path = require('path')
  
  module.exports = {
    stories: ['../src/features/**/__stories__/**/*.stories.js'],
    addons: [
      '@react-theming/storybook-addon',
      'storybook-addon-next-router'
    ],
    features: {
      emotionAlias: false,
      postcss: false
    },
    core: {
      builder: 'webpack5'
    },
    webpackFinal: async (baseConfig) => {
      // Modify or replace config. Mutating the original reference object can cause unexpected bugs.
      const { module = {} } = baseConfig
  
      const newConfig = {
        ...baseConfig,
        module: {
          ...module,
          rules: [...(module.rules || [])]
        }
      }
  
      //
      // CSS Modules
      // Many thanks to https://github.com/storybookjs/storybook/issues/6055#issuecomment-521046352
      //
  
      // First we prevent webpack from using Storybook CSS rules to process CSS modules
      newConfig.module.rules.find(
        rule => rule.test.toString() === '/\\.css$/'
      ).exclude = /\.module\.css$/
  
      // Then we tell webpack what to do with CSS modules
      newConfig.module.rules.push({
        test: /\.module\.css$/,
        include: path.resolve(__dirname, '../features'),
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              modules: true
            }
          }
        ]
      })
  
      return newConfig
    }
  }

My AppBar.js:

  import React, { useState } from 'react'
  import { styled, useTheme } from '@mui/material/styles'
  import MuiDrawer from '@mui/material/Drawer'
  import MuiAppBar from '@mui/material/AppBar'
  import Toolbar from '@mui/material/Toolbar'
  import List from '@mui/material/List'
  import withStyles from '@mui/styles/withStyles'
  import Typography from '@mui/material/Typography'
  import Divider from '@mui/material/Divider'
  import IconButton from '@mui/material/IconButton'
  import MenuIcon from '@mui/icons-material/Menu'
  import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'
  import ChevronRightIcon from '@mui/icons-material/ChevronRight'
  import ListItem from '@mui/material/ListItem'
  import ListItemIcon from '@mui/material/ListItemIcon'
  import ListItemText from '@mui/material/ListItemText'
  import Avatar from '@mui/material/Avatar'
  import AccountCircle from '@mui/icons-material/AccountCircle'
  import MenuItem from '@mui/material/MenuItem'
  import ExitToAppIcon from '@mui/icons-material/ExitToApp'
  import Menu from '@mui/material/Menu'
  import Link from 'next/link'
  import PeopleIcon from '@mui/icons-material/People'
  import CircularProgress from '@mui/material/CircularProgress'
  
  const drawerWidth = 240
  
  const openedMixin = (theme) => ({
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen
    }),
    overflowX: 'hidden'
  })
  
  const closedMixin = (theme) => ({
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen
    }),
    overflowX: 'hidden',
    width: `calc(${theme.spacing(7)} + 1px)`,
    [theme.breakpoints.up('sm')]: {
      width: `calc(${theme.spacing(9)} + 1px)`
    }
  })
  
  const DrawerHeader = styled('div')(({ theme }) => ({
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar
  }))
  
  const AppBar = styled(MuiAppBar, {
    shouldForwardProp: (prop) => prop !== 'open'
  })(({ theme, open }) => ({
    zIndex: theme.zIndex.drawer + 1,
    transition: theme.transitions.create(['width', 'margin'], {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen
    }),
    ...(open && {
      marginLeft: drawerWidth,
      width: `calc(100% - ${drawerWidth}px)`,
      transition: theme.transitions.create(['width', 'margin'], {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.enteringScreen
      })
    })
  }))
  
  const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
    ({ theme, open }) => ({
      width: drawerWidth,
      flexShrink: 0,
      whiteSpace: 'nowrap',
      boxSizing: 'border-box',
      ...(open && {
        ...openedMixin(theme),
        '& .MuiDrawer-paper': openedMixin(theme)
      }),
      ...(!open && {
        ...closedMixin(theme),
        '& .MuiDrawer-paper': closedMixin(theme)
      })
    })
  )
  
  const StyledMenu = withStyles({
    paper: {
      border: '1px solid #d3d4d5'
    }
  })((props) => (
    <Menu
      elevation={0}
      // getContentAnchorEl={null}
      anchorOrigin={{
        vertical: 'bottom',
        horizontal: 'center'
      }}
      transformOrigin={{
        vertical: 'top',
        horizontal: 'center'
      }}
      {...props}
    />
  ))
  
  export default function MiniDrawer ({
    translator: t,
    signOutState = null,
    onSignOut: handleSignOut
  }) {
    const theme = useTheme()
    const [open, setOpen] = useState(false)
    const [anchorEl, setAnchorEl] = useState(null)
  
    const handleMenu = (event) => {
      setAnchorEl(event.currentTarget)
    }
  
    const handleClose = () => {
      setAnchorEl(null)
    }
  
    const handleDrawerOpen = () => {
      setOpen(true)
    }
  
    const handleDrawerClose = () => {
      setOpen(false)
    }
  
    return (
      <>
        <AppBar position='fixed' open={open}>
          <Toolbar>
            <IconButton
              color='inherit'
              aria-label='open drawer'
              onClick={handleDrawerOpen}
              edge='start'
              sx={{
                marginRight: '36px',
                ...(open && { display: 'none' })
              }}
            >
              <MenuIcon />
            </IconButton>
            <Link href='/' passHref>
              <Typography style={{ cursor: 'pointer' }} variant='h6' noWrap component='div'>
                MyApp
              </Typography>
            </Link>
            <Typography sx={{ flexGrow: 1 }} />
            <div>
              <IconButton
                aria-label='account of current user'
                aria-controls='menu-appbar'
                aria-haspopup='true'
                onClick={handleMenu}
                color='inherit'
                size='large'
              >
                <AccountCircle />
              </IconButton>
              <StyledMenu
                id='customized-menu'
                anchorEl={anchorEl}
                keepMounted
                open={Boolean(anchorEl)}
                onClose={handleClose}
              >
                {
                  !signOutState?.processing
                    ? (
                      <MenuItem onClick={handleSignOut}>
                        <ListItemIcon>
                          <ExitToAppIcon fontSize='small' />
                        </ListItemIcon>
                        <ListItemText primary={t('dashboard:sign_out')} />
                      </MenuItem>
                      )
                    : (
                      <MenuItem>
                        <CircularProgress color='inherit' size={24} />
                      </MenuItem>
                      )
                }
              </StyledMenu>
            </div>
          </Toolbar>
        </AppBar>
        <Drawer variant='permanent' open={open}>
          <DrawerHeader>
            <Avatar alt='MyApp' src='/favicon.ico' />
            <IconButton onClick={handleDrawerClose} size='large'>
              {theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
            </IconButton>
          </DrawerHeader>
          <Divider />
          <List>
             <Link href='/users' passHref>
              <ListItem button key={t('dashboard:users')}>
                <ListItemIcon>
                  {' '}
                  <PeopleIcon />{' '}
                </ListItemIcon>
                <ListItemText primary={t('dashboard:users')} />
              </ListItem>
            </Link>
          </List>
        </Drawer>
      </>
    )
  }

And AppBar.stories.js

  /* global module */
  
  import React from 'react'
  import { storiesOf } from '@storybook/react'
  
  import AppBar from '../AppBar'
  import useSignOutMock from '../../__mocks__/hooks/useSignOutMock'
  import useTranslationMock from '../../__mocks__/hooks/useTranslationMock'
  
  function AppBarStory () {
    const {
      signOutState,
      signOut: handleSignOut
    } = useSignOutMock()
    const { translator } = useTranslationMock()
  
    return (
      <AppBar
        translator={translator}
        signOutState={signOutState}
        onSignOut={handleSignOut}
      />
    )
  }
  
  storiesOf('Common Components', module)
    .add('AppBar Component', () => (
      <AppBarStory />
    ))

I fixed it disabling storybook-addon and doing my own decorator:

      import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles'
      import CssBaseline from '@mui/material/CssBaseline'
      import { RouterContext } from 'next/dist/shared/lib/router-context' // next 11.1
      import { ToastProvider } from 'react-toast-notifications'
      import * as nextImage from 'next/image'
      import 'dayjs'
      import 'dayjs/locale/en'
      import 'dayjs/locale/es'
      
      import {
        LocaleProviderMock
      } from '../src/features/commons/__mocks__/hooks/useTranslationMock'
      
      import commonEs from '../public/locales/es/common.json'
      import loginEs from '../public/locales/es/login.json'
      import dashboardEs from '../public/locales/es/dashboard.json'
      import contractEs from '../public/locales/es/contract.json'
      import eventEs from '../public/locales/es/event.json'
      import languageSwitcherEs from '../public/locales/es/languageSwitcher.json'
      import usersEs from '../public/locales/es/users.json'
      import organizationsEs from '../public/locales/es/organizations.json'
      
      import theme from '../src/theme'
      import '../styles/globals.css'
      import 'nprogress/nprogress.css'
      
      const locale = Object.freeze({
        common: commonEs,
        login: loginEs,
        dashboard: dashboardEs,
        contract: contractEs,
        event: eventEs,
        languageSwitcher: languageSwitcherEs,
        users: usersEs,
        organizations: organizationsEs
      })
      
      const CThemeProvider = ({ children, theme }) => (
        <StyledEngineProvider injectFirst>
          <ThemeProvider theme={theme}>
            <ToastProvider autoDismissTimeout={7000} autoDismiss placement='bottom-right'>
              <LocaleProviderMock locale={locale}>
                <CssBaseline />
                {children}
              </LocaleProviderMock>
            </ToastProvider>
          </ThemeProvider>
        </StyledEngineProvider>
      )
      
      Object.defineProperty(nextImage, 'default', {
        configurable: true,
        value: props => {
          return (
            <div
              style={{
                position: 'relative'
              }}
            >
              <img
                style={{
                  objectFit: 'cover',
                  minWidth: '100%',
                  minHeight: '100%',
                  maxWidth: '100%',
                  maxHeight: '100%'
                }}
                {...props}
              />
            </div>
          )
        },
      })
      
      export const decorators = [
        Story => (
          <CThemeProvider theme={theme}>
            <Story />
          </CThemeProvider>
        )
      ]
      
      export const parameters = {
        nextRouter: {
          Provider: RouterContext.Provider,
          path: '/', // defaults to `/`
          asPath: '/', // defaults to `/`
          query: {}, // defaults to `{}`
          push() {
          } // defaults to using addon actions integration,
          //   can override any method in the router
        }
      }

emotion 11 conflicts

Hi There,

Is this repo and add-on still maintained? I'm having conflicts because this addon has emotion10 as a devDependency but my components are using v11.

Thanks,

Chris

"MuiInputBase" isn't affected by the ThemeProvider (and crashes)

Buttons and Tables work fine, the themes are switched and look ok, but everything related to MuiInputBase (so basically textfields, autocompletes and such) crash the preview when switching to Docs (Canvas is ok) with a Cannot read property 'mode' of undefined (that is theme.palette.mode).

My setup is:

// preview.js
import React from 'react'
import { ThemeProvider } from '@material-ui/core';
import { addDecorator } from '@storybook/react';
import { withThemes } from '@react-theming/storybook-addon';
import { THEMES } from '../src/constants';
import { createTheme } from '../src/theme/index'

const providerFn = ({ theme, children }) => {
  const config = {
    direction: 'ltr',
    theme: theme,
    roundedCorners: false
  }

  const muTheme = createTheme(config)
  return <ThemeProvider theme={muTheme}>{children}</ThemeProvider>;
};

const onThemeSwitch = context => {
  const { theme } = context;

  const background = theme === 'LIGHT' ? '#f4f5f7' : '#252A36';
  const parameters = {
    backgrounds: {
      default: background,
    },
  };
  return {
    parameters,
  };
};

addDecorator(withThemes(null, [THEMES.LIGHT, THEMES.DARK, THEMES.NATURE], { providerFn, onThemeSwitch }));
// createTheme
export const createTheme = (config: ThemeConfig = {}): Theme => {
  let themeOptions = themesOptions[config.theme];

  if (!themeOptions) {
    console.warn(new Error(`The theme ${config.theme} is not valid`));
    themeOptions = themesOptions[THEMES.LIGHT];
  }

  let theme = createMuiTheme(
    merge(
      {},
      baseOptions,
      themeOptions,
      {
        ...(
          config.roundedCorners && {
            shape: {
              borderRadius: 16
            }
          }
        )
      },
      {
        direction: config.direction
      }
    )
  );

  if (config.responsiveFontSizes) {
    theme = responsiveFontSizes(theme);
  }

  return theme;
};

The theme and everything else work fine on the actual website.

React-theming sb addon ruins everything down

import { ThemeProvider } from '@material-ui/core/styles';
import { defaultMuiTheme as theme} from '../src/themes';
import { withThemes } from '@react-theming/storybook-addon';

const providerFn = ({ theme, children }) => {
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};

addDecorator(withThemes(null, [theme], { providerFn }));

instant of

const themeDecorator = storyFn => (
  <ThemeProvider theme={theme}>
    {storyFn()}
  </ThemeProvider>
);

addDecorator(themeDecorator);

image

It is the same with @react-theming/storybook-addon only out of sb config or with additional one too.

  "dependencies": {
    ...
    "@material-ui/core": "4.11.2",
    "@material-ui/icons": "4.11.2",
    "@material-ui/lab": "4.0.0-alpha.57",
    "@material-ui/pickers": "3.2.10",
    "@material-ui/styles": "4.11.2",
    ...
    "react": "17.0.1",
    "react-dom": "17.0.1",
  },
  "devDependencies": {
    ...
    "@react-theming/storybook-addon": "^1.1.1",
    "@storybook/react": "^6.1.21",
    ...

What is the reason it could be?

Theming Option Not Appearing In Storybook

I am wanting to switch themes but the Theming Option is not appearing in the panel in Storybook
I've tried a few different versions of the react theming library but cannot change themes. The theme provider is being added with the decorator because the components render when it is there and don't when it is not as expected.

This is my related dependencies

"emotion-theming": "^10.0.27",
  "devDependencies": {
    "@react-theming/storybook-addon": "^1.1.1",
    "@storybook/addon-actions": "^6.3.6",
    "@storybook/addon-essentials": "^6.3.6",
    "@storybook/addon-links": "^6.3.6",
    "@storybook/react": "^6.3.6",
    "storybook-addon-i18next": "^1.3.0",
    "storybook-react-router": "^1.0.8",
    "typescript": "^4.2.2",
    "webpack": "^5.39.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0",
....
  },

main.js

module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    'storybook-addon-i18next/register',
    'storybook-react-router/register',
    '@react-theming/storybook-addon'
  ],
  typescript: {
    reactDocgen: 'none',
  }
}

preview.js


import { addDecorator } from '@storybook/react'
import { ThemeProvider } from 'emotion-theming';
import StoryRouter from 'storybook-react-router';
import { Suspense } from 'react'
import { withThemes } from '@react-theming/storybook-addon';
import {themeVariables} from '../src/utils/themes'

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

addDecorator(withThemes(ThemeProvider, themeVariables));
addDecorator((story, context) => (
  <Suspense fallback="Loading...">{story(context)}</Suspense>
));
addDecorator(StoryRouter());

Any thoughts on why this is not working?

issue

Theme values gets stripped down

We're using themes according to styled-system theme specification: https://styled-system.com/theme-specification#scale-aliases

For example, we define fields like this, which combines numeric indexes with string keys as aliases:

theme.fontSizes = ['12', '16,' '20'];
theme.fontSizes.sm = theme.fontSizes[0];
theme.fontSizes.md = theme.fontSizes[1];
theme.fontSizes.lg = theme.fontSizes[2];

This works in regular usages, but on Storybook (with the addon) the aliases keys are stripped down and all we're getting is the numeric indexes:

['12', '16,' '20'];

When debugging, I saw that initially, we have those aliases, but on rerender (on the 2nd hit of the debugger, which occurs immediately) the aliases disappear.

Any idea why this is happening?

Breaks background selection on canvas with @storybook/addon-essentials

The strange thing with this bug is that background selection work fine with this addon in docs just not in canvas.

the backgrounds add on seems to style the div with the class 'sb-main-padded' this seems to be stuck with:
background-color: #fffff
when using react-theming addon.

I'm guessing under the hood they might be using theme provider decorators, no idea why docs is fine but canvas isn't.

Change background color with the theme

It should be automatic that depending on the theme, it's easy to set the background color of the story. Currently the only way I've found is adding a div wrapper in the providerFn, but it's a limited solution because it shows some ugly unthemed borders.

Support for Storybook v7

Storybook v7 is in beta for a while now, and looks like this addon doesn't support it yet.


From my tests, it appears that a change in the default export of @storybook/addons is affecting @storybook/addon-devkit which is used by @react-theming/storybook-addon.

Since addon-devkit has not been updated in a couple of years, it would be nice to follow their recommendation and migrate to @storybook/addon-kit, which already supports v7.

Using with MantineJS

Hi!
I found your plugin for storybook and I think it looks perfect for what I'm building,
Only issue is that I'm using MantineJS for my styling and i dont seem to be able to get it to work.
Im unsure if it currently supports MantineJS?
Thank you

Storybook 8 compatibility

Hey all! I’m reaching out from the core SB team :)

Storybook 8 (our next major release) is coming soon, and it introduces some breaking changes that your addon might need to account for.

We’ve listed all the key changes in a new Storybook 8 migration guide, and we’d encourage you to check it out and see if your addon is impacted.

We also have an addons channel in our Discord community, which we’d like to use to better communicate with addon authors in the future. If you’re not part of the server, consider joining here and message me (@joevaugh4n) so that I can give you the addon creator role! If you’re already in the server, please just ping me and I’ll respond to you there.

Thanks for being a part of our addon community!

Joe

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.