I've been working on pulling our existing react FE components out of our main repo, and into a separate repo that I am bundling with rollup. Our old code was using makeStyles
and I have been switching that over to styled-components
but still keeping the previous MUI theme. I've setup storybook and am wrapping that in styled components theme provider, in order to access the theme inside the styled components.
The structure looks like
components
\src
index.ts(imports and exports components)
\theme(MUI theme)
\components
\buttons
button.tsx(react button code)
index.ts(imports and exports button)
\lib(rollup spits this out)
Finally, to the question. After I bundle everything with rollup, I do an NPM install, and import it into a different project. The problem is, I'm not getting the proper theming in the imported components. Here is a somewhat simplified version of my button.
import React from "react";
import { Button as MaterialButton, ButtonProps } from "@material-ui/core";
import styled from "styled-components";
export interface MyButtonProps extends ButtonProps {
error?: boolean;
target?: string;
}
const StyledButton = styled(MaterialButton)`
&.error {
background: ${(props) => props.theme.palette.error.main};
color: #fff;
&:hover {
background: ${(props) => props.theme.palette.error.main};
}
}
`;
const Button = ({
error,
className,
...rest}: MyButtonProps) => {
className += error ? " error" : "";
return (
<StyledButton
{...rest}
className={className}
>
{children}
</StyledButton>
);
};
export default Button;
So, if I put error
attribute on the button, I do get the correct color from my theme. However, if I put color="primary"
I do not get the correct color. I also don't have any of my base styles from the theme.
I haven't been able to figure out how to get this theme into the components I'm bundling with rollup. Finally, here is my rollup config.
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "rollup-plugin-typescript2";
import postcss from "rollup-plugin-postcss";
import svg from "rollup-plugin-svg-import";
const packageJson = require("./package.json");
export default {
input: "src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
svg(),
typescript({ useTsconfigDeclarationDir: true }),
postcss({
extensions: [".css"],
}),
],
};
For anyone who has stumbled upon this and is curious about the answer. Here is what I ended up doing. Hopefully this is the correct solution. One thing that is a bummer, I end up with MUI
ThemeProvider
giving me it's generated class names. This means in my styled components, I'll occasionally need to do this to target things [class^="MuiSvgIcon-root"]
, but maybe i can access the class through props, still messing with it. Anyway, here is the button.
import React from "react";
import { Button as MaterialButton, ButtonProps } from "@material-ui/core";
import styled from "styled-components";
import { ThemeProvider } from "@material-ui/core/styles";
import theme from "../../../theme";
export interface MyButtonProps extends ButtonProps {
error?: boolean;
target?: string;
}
const StyledButton = styled(MaterialButton)`
&.error {
background: ${theme.palette.error.main};
color: #fff;
&:hover {
background: ${theme.palette.error.main};
}
}
`;
const Button = ({
error,
size,
variant,
endIcon,
children,
className,
...rest
}: MyButtonProps) => {
if (className && error) {
className += " error";
} else if (!className && error) {
className = "error";
}
return (
<ThemeProvider theme={theme}>
<StyledButton
{...rest}
variant={variant}
size={size}
endIcon={endIcon}
className={className}
>
{children}
</StyledButton>
</ThemeProvider>
);
};
export default Button;
I guess each component will need to be wrapped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With