I have this web component created with Preact and I'm trying to use Material ui to style it. Reading Preacts documentation, https://preactjs.com/about/libraries-addons/, it claims to have support for material ui. However when Im running the app locally it gives an error as material ui has a dependency to react.
I installed mui using:
npm install @mui/material @emotion/react @emotion/styled
Then I copied an empample from mui docs to make the moste basic slider:
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Slider from "@mui/material/Slider";
export default function ContinuousSlider() {
return (
<Box sx={{ width: 200 }}>
<Slider disabled defaultValue={30} aria-label="Disabled slider" />
</Box>
);
}
I get the html for the slider in my shadow-dom but it's commpletely unstyled so I can't see it without inspecting the code.
I also tried usint preact-material-components but the result was the same plus I'm a bit reluctant to use that since it hasn't benn updated in four years.
The project is set up with Vite and my vite.config.js
looks like:
import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [preact()],
});
EDIT:
I tried to make a really simple reproduction of the files contained here:
I have this web component built with Preact and I'm tryng to add Mui styling to it. It works fine until I turn on the shadow root.
Basically I have the following files. 'index.html':
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" />
<title>Slider</title>
</head>
<body>
<script type="module" src="/index.jsx"></script>
<slider-component></slider-component>
</body>
</html>
index.jsx
:
import register from "preact-custom-element";
import Slider from "./src/Slider";
register(Slider, "slider-component", [], { shadow: true });
and Slider.jsx
import Slider from "@mui/material/Slider";
export default function ContinuousSlider() {
return <Slider defaultValue={30} aria-label="Disabled slider" />;
}
Then I have jsconfig.json
which looks like:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true,
"allowJs": true,
"checkJs": true,
/* Preact Config */
"jsx": "react-jsx",
"jsxImportSource": "preact",
"skipLibCheck": true,
"paths": {
"react": ["./node_modules/preact/compat/"],
"react-dom": ["./node_modules/preact/compat/"]
}
},
"include": ["node_modules/vite/client.d.ts", "**/*"]
}
and package.json
that looks like:
{
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.15",
"preact": "^10.13.1",
"preact-custom-element": "^4.3.0",
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat"
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
"eslint": "^8.56.0",
"eslint-config-preact": "^1.3.0",
"vite": "^4.3.2"
},
"eslintConfig": {
"extends": "preact"
}
}
plus vite.config.js
that looks like:
import { defineConfig } from 'vite';
import preact from '@preact/preset-vite';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [preact()],
});
The problem occurs when I change from { shadow: false }
to { shadow: true }
in index.jsx
I got it working following Material ui's document on Shadow DOM, useing CacheProvider
and createCache
from emotion.
I also had to register the web-component with {shadow: false}
and then attach a shadow to it that I could use in the cache. Finally I rendered my App inside the CashProvider
targeting the newly created shadow root element.