diff --git a/docs/data/material/integrations/styled-components/styled-components.md b/docs/data/material/integrations/styled-components/styled-components.md index 62f0c1b4af7447..4d2b9a2999d680 100644 --- a/docs/data/material/integrations/styled-components/styled-components.md +++ b/docs/data/material/integrations/styled-components/styled-components.md @@ -95,3 +95,73 @@ For TypeScript, you must also update the `tsconfig.json` as shown here: :::info **Versions compatibility**: To ensure compatibility, it's essential to align the major version of `@mui/styled-engine-sc` with that of the `styled-components` package you're using. For instance, if you opt for `styled-components` version 5, it's necessary to use `@mui/styled-engine-sc` version 5. Similarly, if your preference is `styled-components` version 6, you'll need to upgrade `@mui/styled-engine-sc` to its version 6, which is currently in an alpha state. ::: + +## Vite/Vitest configuration + +When using Material-UI with styled-components and Vite/Vitest, you may encounter ESM/CJS compatibility issues. Here are the recommended configurations: + +### Option 1: Using fallbackCJS (Recommended) + +Add the following to your `vite.config.ts`: + +```ts title="vite.config.ts" +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + test: { + environment: 'jsdom', + globals: true, + server: { + deps: { + fallbackCJS: true, + }, + }, + }, + plugins: [react()], +}); +``` + +### Option 2: Using inline dependencies + +Alternatively, you can inline the MUI packages: + +```ts title="vite.config.ts" +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + test: { + environment: 'jsdom', + globals: true, + server: { + deps: { + inline: [ + '@mui/material', + '@mui/system', + '@mui/styled-engine', + '@mui/icons-material', + // Add other MUI packages you're using + '@mui/x-date-pickers', + ], + }, + }, + }, + plugins: [react()], +}); +``` + +### Package.json configuration + +When using Vite, you must also override the styled-engine in your `package.json`: + +```json title="package.json" +{ + "dependencies": { + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" + }, + "resolutions": { + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" + } +} +``` diff --git a/packages/mui-styled-engine-sc/package.test.json b/packages/mui-styled-engine-sc/package.test.json new file mode 100644 index 00000000000000..a15de633b46011 --- /dev/null +++ b/packages/mui-styled-engine-sc/package.test.json @@ -0,0 +1,24 @@ +{ + "name": "@mui/styled-engine-sc-vite-test", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "test": "vitest", + "test:ui": "vitest --ui", + "test:coverage": "vitest --coverage" + }, + "dependencies": { + "@mui/styled-engine-sc": "workspace:*", + "styled-components": "^6.0.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.0.0", + "@vitest/ui": "^1.0.0", + "vitest": "^1.0.0", + "jsdom": "^23.0.0" + }, + "overrides": { + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" + } +} \ No newline at end of file diff --git a/packages/mui-styled-engine-sc/src/index.js b/packages/mui-styled-engine-sc/src/index.js index ef12d36e310751..1710c737431fcb 100644 --- a/packages/mui-styled-engine-sc/src/index.js +++ b/packages/mui-styled-engine-sc/src/index.js @@ -1,5 +1,4 @@ -import scStyled from 'styled-components'; - +import { styled as scStyled } from 'styled-components'; export default function styled(tag, options) { let stylesFactory; diff --git a/packages/mui-styled-engine-sc/src/vite-vitest.test.js b/packages/mui-styled-engine-sc/src/vite-vitest.test.js new file mode 100644 index 00000000000000..f323ccfeb44e21 --- /dev/null +++ b/packages/mui-styled-engine-sc/src/vite-vitest.test.js @@ -0,0 +1,91 @@ +import * as React from 'react'; +import { expect } from 'chai'; +import { createRenderer } from '@mui/internal-test-utils'; +import styled from '@mui/styled-engine-sc'; + +describe('Vite/Vitest compatibility', () => { + const { render } = createRenderer(); + + it('should work with named import from styled-components (Vite/Vitest fix)', () => { + // This test verifies that the fix for Vite/Vitest compatibility works + // The issue was that styled-components v6+ changed to named exports + // but mui-styled-engine-sc was using default import + const StyledComponent = styled('div')({ + color: 'red', + padding: '10px', + }); + + const { container } = render(Test Content); + + expect(container.firstChild).not.to.equal(null); + expect(container.firstChild.tagName).to.equal('DIV'); + expect(container.firstChild.textContent).to.equal('Test Content'); + }); + + it('should work with complex styled components in Vite/Vitest', () => { + const ComplexStyledComponent = styled('button')(({ theme }) => ({ + backgroundColor: 'blue', + color: 'white', + padding: '8px 16px', + border: 'none', + borderRadius: '4px', + cursor: 'pointer', + '&:hover': { + backgroundColor: 'darkblue', + }, + })); + + const { container } = render(Click me); + + expect(container.firstChild).not.to.equal(null); + expect(container.firstChild.tagName).to.equal('BUTTON'); + expect(container.firstChild.textContent).to.equal('Click me'); + }); + + it('should handle styled-components options correctly in Vite/Vitest', () => { + const StyledWithOptions = styled('span', { + shouldForwardProp: (prop) => prop !== 'customColor', + label: 'ViteTestComponent', + })(({ customColor }) => ({ + color: customColor || 'black', + })); + + const { container } = render(Styled Text); + + expect(container.firstChild).not.to.equal(null); + expect(container.firstChild.tagName).to.equal('SPAN'); + expect(container.firstChild.textContent).to.equal('Styled Text'); + // The customColor prop should not be forwarded to the DOM + expect(container.firstChild).not.to.have.attribute('customColor'); + }); + + it('should support ThemeContext from styled-components in Vite/Vitest', async () => { + const { ThemeContext } = await import('@mui/styled-engine-sc'); + expect(ThemeContext).not.to.equal(undefined); + expect(typeof ThemeContext).to.equal('object'); + }); + + it('should support keyframes from styled-components in Vite/Vitest', async () => { + const { keyframes } = await import('@mui/styled-engine-sc'); + expect(keyframes).not.to.equal(undefined); + expect(typeof keyframes).to.equal('function'); + + const animation = keyframes` + from { opacity: 0; } + to { opacity: 1; } + `; + expect(animation).not.to.equal(undefined); + }); + + it('should support css from styled-components in Vite/Vitest', async () => { + const { css } = await import('@mui/styled-engine-sc'); + expect(css).not.to.equal(undefined); + expect(typeof css).to.equal('function'); + + const styles = css` + color: red; + padding: 10px; + `; + expect(styles).not.to.equal(undefined); + }); +}); \ No newline at end of file diff --git a/packages/mui-styled-engine-sc/vite.config.test.js b/packages/mui-styled-engine-sc/vite.config.test.js new file mode 100644 index 00000000000000..20d113cc8eaa25 --- /dev/null +++ b/packages/mui-styled-engine-sc/vite.config.test.js @@ -0,0 +1,32 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// Vite configuration for testing MUI styled-components compatibility +export default defineConfig({ + plugins: [react()], + test: { + environment: 'jsdom', + globals: true, + // Test both with and without fallbackCJS to ensure the fix works + server: { + deps: { + // Uncomment to test with fallbackCJS (should work with both) + // fallbackCJS: true, + + // Alternative: inline MUI packages (should work with both) + // inline: [ + // '@mui/material', + // '@mui/system', + // '@mui/styled-engine', + // '@mui/styled-engine-sc', + // ], + }, + }, + }, + resolve: { + alias: { + // Ensure we're using the styled-engine-sc version + '@mui/styled-engine': '@mui/styled-engine-sc', + }, + }, +}); \ No newline at end of file