Skip to content

I hope to use storybook MUI to create the new UI library, but the themes from material ui and joy ui can not work together, help me please. #43238

Open
@rick-liyue-huang

Description

@rick-liyue-huang

Steps to reproduce

Link to live example: (required)

Steps:

  1. I create the .storybook/preview.tsx, to confirm the mui material and mui joy working together
// .storybook/preview.ts
import React, { FC, ReactNode, Suspense, useMemo } from 'react';
import type { Preview } from '@storybook/react';
// import { I18nextProvider  } from '@storybook/react';
import { I18nextProvider } from 'react-i18next';
import i18n from '../src/i18n'; // Adjust the path if necessary
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
import { ThemeProvider, StyledEngineProvider } from '@mui/material';

import {
    experimental_extendTheme as materialExtendTheme,
    Experimental_CssVarsProvider as MaterialCssVarsProvider,
    THEME_ID as MATERIAL_THEME_ID,
} from '@mui/material/styles';
import {
    CssVarsProvider as JoyCssVarsProvider,
    ThemeProvider as JoyThemeProvider,
    THEME_ID as JOY_THEME_ID,
} from '@mui/joy/styles';
import CssBaseline from '@mui/material/CssBaseline';

import { darkTheme } from '../src/themes/dark.theme';
import { lightTheme } from '../src/themes/light.theme';
import { joyThemes } from '../src/themes/joy.themes';

// import '../src/index.css';

import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import '@fontsource/material-icons';

const THEMES = {
    light: lightTheme,
    dark: darkTheme,
};

// Decorator to wrap stories with I18nextProvider
const withI18next = (Story: FC) => {
    return (
        // This catches the suspense from components not yet ready (still loading translations)
        // Alternative: set useSuspense to false on i18next.options.react when initializing i18next
        <Suspense fallback={<div>loading translations...</div>}>
            <I18nextProvider i18n={i18n}>
                <Story />
            </I18nextProvider>
        </Suspense>
    );
};

const withTheme = (Story: FC, context) => {
    const { theme: themeKey } = context.globals;
    const theme = useMemo(
        () => THEMES[themeKey] || THEMES['light'],
        [themeKey]
    );

    // const materialTheme = materialExtendTheme();

    return (
        <StyledEngineProvider injectFirst>
            {/* <ThemeProvider theme={theme}> */}
            <ThemeProvider theme={{ [MATERIAL_THEME_ID]: theme }}>
                <MaterialCssVarsProvider theme={joyThemes}>
                    <CssBaseline enableColorScheme />
                    <Story />
                </MaterialCssVarsProvider>
                </ThemeProvider>
            {/* </ThemeProvider> */}
        </StyledEngineProvider>
    );
};

const withNewTheme = withThemeFromJSXProvider({
    themes: {
        light: lightTheme,
        dark: darkTheme,
    },
    defaultTheme: 'light',
    Provider: ThemeProvider,
    GlobalStyles: CssBaseline,
});

const preview: Preview = {
    decorators: [withI18next, withTheme], // Add the i18n decorator here
    parameters: {
        actions: { fn: '^on[A-Z].*' },
        controls: {
            expanded: true, // will show all controls by default
            matchers: {
                color: /(background|color)$/i,
                date: /Date$/i,
            },
        },
    },
};

export default preview;
  1. I hope to apply theme on the new Ui library;
  2. I create the 'joy.themes.ts' to confirm the 'JoyInput' component;
import { extendTheme } from '@mui/joy/styles';

export const joyThemes = extendTheme({
    colorSchemes: {
        dark: {
            palette: {
                primary: {
                    50: '#C0CCD9',
                    100: '#A5B8CF',
                    200: '#6A96CA',
                    300: '#f00',
                    400: '#0f0',
                    500: '#00f',
                    600: '#1B62B5',
                    700: '#265995',
                    800: '#2F4968',
                    900: '#ddd',
                },
            },
        },
        light: {
            palette: {
                primary: {
                    50: '#232323',
                    100: '#C2D0E3',
                    200: '#8AA4C8',
                    300: '#f0f',
                    400: '#ff0',
                    500: '#0ff',
                    600: '#005FA5',
                    700: '#00508D',
                    800: '#00426F',
                    900: '#333',
                },
            },
        },
    },
    components: {
        JoyInput: {
            styleOverrides: {
                root: ({ theme, ownerState }) => {
                    console.log('JoyInput theme applied', { theme, ownerState });
                    return {
                        ...(ownerState.variant === 'solid' && {
                            backgroundColor: theme.vars.palette.primary[300],
                        })
                    }
                }
            }
        },
    },
});

// Then, pass it to `<CssVarsProvider theme={theme}>`.
  1. I also create the Input component.
import React from 'react';
import { cva, VariantProps } from 'class-variance-authority';
import { cn } from '../../utils/index';
import { Input as JoyInput, InputProps as JoyInputProps } from '@mui/joy';
import styles from './customize.module.css';

const InputStyles = cva([''], {
    variants: {
        size: {
            lg: styles.large,
            md: styles.medium,
            sm: styles.small,
        },
    },
    compoundVariants: [
        {
            size: 'lg',
        },
    ],
    defaultVariants: {
        size: 'lg',
    },
});

type InputBaseProps = Pick<
    JoyInputProps,
    | 'variant'
    | 'startDecorator'
    | 'endDecorator'
    | 'disabled'
    | 'onChange'
    | 'type'
    | 'placeholder'
> &
    VariantProps<typeof InputStyles>;

export interface InputProps extends InputBaseProps {
    className?: string;
    style?: React.CSSProperties;
}

export const Input = ({ className, style, size, ...rest }: InputProps) => {
    return (
        <JoyInput
            {...rest}
            className={cn(InputStyles({ size }), className)}
            style={style}
        />
    );
};
  1. I also created Button component by using Button from '@mui/material', the button can applied the proper theme color, but the 'Input' component not working well, he only can show light theme color, but not work on dark theme color.

Current behavior

the JoyInput component theme is working fine on 'light' only

Expected behavior

i hope that the JoyInput component can work on both themes. I hope that the 'backgroundColor' become 'red' when in dark theme.

Context

I hope to create the new UI library.

Your environment

npx @mui/envinfo
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.

Search keywords: storybook, MUI, @mui/material, @mui/joy

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions