Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Theme Switching from Getting started with @mui/material doesn't work#33355

Unanswered
thediveo asked this question inHelp
Discussion options

Summary

Abstract

The instructions laid out in the "Getting started with @mui/material" don't work for me correctly; when switching to a dark theme the stories (canvasses) don't take on a dark background.

Example Screenshot

Notice how the dark theme is selected. The lighter blue text color indicates that this particular dark theme parameter has been applied. However, the rendered story does not get a dark background.

dark theme background not applied

What am I overlooking here?

Details

My current project setup can be found in this branch:https://github.com/thediveo/lxkns/tree/chore/web/web/lxkns

  • Storybook 10
  • Vite 7
  • React 19
  • MUI 7
"@emotion/react":"^11.14.0","@emotion/styled":"^11.14.1","@mui/material":"^7.3.6","@mui/system":"^7.3.6","@storybook/addon-docs":"^10.1.4","@storybook/addon-links":"^10.1.4","@storybook/addon-themes":"^10.1.8","@storybook/react-vite":"^10.1.4","storybook":"^10.1.4",
// .storybook/main.tsimporttype{StorybookConfigasStorybookViteConfig}from'@storybook/react-vite'constconfig:StorybookViteConfig={framework:{name:'@storybook/react-vite',options:{},},stories:['../src/**/*.stories.@(ts|tsx)',],addons:['@storybook/addon-docs','@storybook/addon-links','@storybook/addon-themes',],docs:{},core:{disableTelemetry:true,disableWhatsNewNotifications:true,},typescript:{check:true,},}exportdefaultconfig
// .storybook/preview.tsximport{BrowserRouter}from'react-router-dom'importtype{Preview}from'@storybook/react-vite'import{withThemeFromJSXProvider}from'@storybook/addon-themes'import'@fontsource/roboto/300.css'import'@fontsource/roboto/400.css'import'@fontsource/roboto/500.css'import'@fontsource/roboto/700.css'import'@fontsource/roboto-mono/400.css'import{lxknsDarkTheme,lxknsLightTheme}from'../src/app/appstyles'import{createTheme,StyledEngineProvider,ThemeProvider}from'@mui/material/styles'importCssBaselinefrom'@mui/material/CssBaseline'constlightTheme=createTheme({components:{MuiSelect:{defaultProps:{variant:'standard',// MUI v4 default.},},},palette:{mode:'light',primary:{main:'#3f51b5',},secondary:{main:'#f50057',},},},lxknsLightTheme,)constdarkTheme=createTheme({components:{MuiSelect:{defaultProps:{variant:'standard',// MUI v4 default.},},},palette:{mode:'dark',},},lxknsDarkTheme,)constpreview:Preview={decorators:[(Story)=>(<BrowserRouterbasename=''><StyledEngineProviderinjectFirst><Story/></StyledEngineProvider></BrowserRouter>),withThemeFromJSXProvider({themes:{light:lightTheme,dark:darkTheme,},defaultTheme:'dark',Provider:ThemeProvider,GlobalStyles:CssBaseline,}),],}exportdefaultpreview

Additional information

No response

Create a reproduction

No response

You must be logged in to vote

Replies: 1 comment 14 replies

Comment options

Hi@thediveo! I'mDosu and I’m helping the storybook team.

The issue is that Storybook's theme switcher and background switcher are separate by default, so toggling to a dark theme with MUI doesn't automatically update the canvas background. To fix this, you should:

  1. Add a backgrounds parameter in your.storybook/preview.tsx to define light and dark backgrounds for the canvas. For example:
exportconstparameters={backgrounds:{default:'dark',values:[{name:'light',value:'#fff'},{name:'dark',value:'#121212'},// or your preferred dark bg],},};

This ensures the canvas background can be toggled and matches your theme[source].

  1. To sync the theme and background so that switching to dark mode also updates the canvas, add a decorator that watches the theme and sets the background accordingly. For example:
import{useEffect}from'react';constwithBackgroundSync=(Story,context)=>{useEffect(()=>{constisDark=context.globals.theme==='dark';document.body.style.background=isDark ?'#121212' :'#fff';},[context.globals.theme]);return<Story/>;};exportconstdecorators=[withBackgroundSync,// ...your other decorators];

This approach ensures the canvas background updates with your MUI theme[source].

  1. Make sure your custom MUI themes (lxknsDarkTheme,lxknsLightTheme) set thepalette.background.default property, as MUI uses this for the page background.

If you want a unified toggle for both theme and background, you can also look into using only the theme switcher and syncing the background via a decorator as above[source].

Try these steps and you should see the canvas background update when switching themes. If you still have issues, double-check that your theme and background values match and that the decorator is applied.

To reply, just mention@dosu.


How did I do?Good |Irrelevant |Incorrect |Verbose |Hallucination |Report 🐛 |Other

Chat with Dosu Open in Cursor Join Discord Share on X

You must be logged in to vote
14 replies
@dosubot
Comment options

You're right—useEffect can only be used inside React components, not in plain functions or non-component decorators. The previous code was incorrect for that reason[source].

To sync your MUI theme and the Storybook canvas background without misusing hooks, you need to imperatively update the background using DOM manipulation in your decorator. Here’s how you can do it in your.storybook/preview.tsx:

import{BrowserRouter}from'react-router-dom';importtype{Preview}from'@storybook/react-vite';import{withThemeFromJSXProvider}from'@storybook/addon-themes';import'@fontsource/roboto/300.css';import'@fontsource/roboto/400.css';import'@fontsource/roboto/500.css';import'@fontsource/roboto/700.css';import'@fontsource/roboto-mono/400.css';import{lxknsDarkTheme,lxknsLightTheme}from'../src/app/appstyles';import{createTheme,StyledEngineProvider,ThemeProvider}from'@mui/material/styles';importCssBaselinefrom'@mui/material/CssBaseline';constlightTheme=createTheme({/* ... */palette:{mode:'light',background:{default:'#fff'}}},lxknsLightTheme,);constdarkTheme=createTheme({/* ... */palette:{mode:'dark',background:{default:'#121212'}}},lxknsDarkTheme,);exportconstparameters={backgrounds:{default:'dark',values:[{name:'light',value:lightTheme.palette.background.default},{name:'dark',value:darkTheme.palette.background.default},],},};functionsyncCanvasBackground(context){constisDark=context.globals.theme==='dark';constcanvas=document.querySelector('.sb-show-main');if(canvas){canvas.style.background=isDark      ?darkTheme.palette.background.default      :lightTheme.palette.background.default;}constdocs=document.querySelector(`#anchor--${context.id} .docs-story`);if(docs){docs.style.background=isDark      ?darkTheme.palette.background.default      :lightTheme.palette.background.default;}}constwithCanvasBackgroundSync=(Story,context)=>{// Imperatively sync background on every rendersyncCanvasBackground(context);return(<Story/>);};constpreview:Preview={decorators:[(Story)=>(<BrowserRouterbasename=""><StyledEngineProviderinjectFirst><Story/></StyledEngineProvider></BrowserRouter>),withThemeFromJSXProvider({themes:{light:lightTheme,dark:darkTheme},defaultTheme:'dark',Provider:ThemeProvider,GlobalStyles:CssBaseline,}),withCanvasBackgroundSync,],};exportdefaultpreview;

This avoids hooks entirely and updates the background directly[source]. If you want to avoid style leakage, you can also clear the background style at the start of the decorator.

Let me know if you need a version that also handles Docs view more robustly or if you want to discuss other approaches (like using a wrapper component or custom DocsContainer).

To reply, just mention@dosu.


How did I do?Good |Irrelevant |Incorrect |Verbose |Hallucination |Report 🐛 |Other

Chat with Dosu Open in Cursor Join Discord Share on X

@thediveo
Comment options

the original code is in preview.tsx so it its TSX. make your code correct TSX.

@thediveo
Comment options

canvas.style doesnt exist

@dosubot
Comment options

You're right—canvas.style doesn't exist in Storybook 10 because Storybook applies backgrounds by injecting CSS targeting container selectors, not by setting inline styles on a single element. The correct way to sync your MUI theme background with the Storybook canvas is to inject a<style> element that targets.sb-show-main (Canvas) and#anchor--<story-id> .docs-story (Docs) with your desired background color reference.

Here's a TSX-compatible decorator you can add to your.storybook/preview.tsx that imperatively injects or updates a style tag on every render, avoiding hooks and direct DOM style manipulation:

functionsetStorybookBackground(theme:'light'|'dark',storyId:string,lightBg:string,darkBg:string){conststyleId='custom-mui-bg-sync';constselectorCanvas='.sb-show-main';constselectorDocs=`#anchor--${storyId} .docs-story`;constcolor=theme==='dark' ?darkBg :lightBg;constcss=`${selectorCanvas},${selectorDocs} {      background:${color} !important;      transition: background 0.3s;    }  `;letstyleTag=document.getElementById(styleId)asHTMLStyleElement|null;if(!styleTag){styleTag=document.createElement('style');styleTag.id=styleId;document.head.appendChild(styleTag);}styleTag.textContent=css;}constwithMuiBackgroundSync=(Story,context)=>{// Get theme and background colors from your themesconsttheme=context.globals.theme==='dark' ?'dark' :'light';setStorybookBackground(theme,context.id,lightTheme.palette.background.default,darkTheme.palette.background.default);return<Story/>;};

Add this as the last decorator in your array, after yourwithThemeFromJSXProvider. This will ensure the background updates for both Canvas and Docs views, and you won't run into issues with missing or undefined elements reference.

If you want an alternative, you can also wrap your stories in a styled container that sets the background from the theme, but the above approach most closely matches how Storybook manages backgrounds internally.

Let me know if you want a full preview.tsx example with this pattern.

To reply, just mention@dosu.


How did I do?Good |Irrelevant |Incorrect |Verbose |Hallucination |Report 🐛 |Other

Chat with Dosu Open in Cursor Join Discord Share on X

@thediveo
Comment options

This is an incorrect answer that shows that this forum uses a blabla generator. Maybe a true human can take over, this is going nowhere. This blabla generator experiment has failed; this is no forum, this is a sick joke.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Help
Labels
None yet
1 participant
@thediveo

[8]ページ先頭

©2009-2025 Movatter.jp