mui / mui/material-ui

Custom MUI library fails to get App Theme

Open
#47,704 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

customization: theme scope: system support: question
Dominant language
JavaScript
Stars
99.1k
Forks
32.5k
Avg merge
2d 17h
Merged PRs (30d)
106

Description

Steps to reproduce

Cannot provide a live example as the code being developed is confidential for the company I work for (not my rules)

Current behavior

Custom library built on top of MUI does not use the theme provided my the app importing the library; instead using the default theme,

Expected behavior

The components in the library (built using MUI components) should use the theme provided by the app and not the default theme.

Context

I am creating a component library built on top of MUI. These are just a series of component we use frequently on our projects and instead of copying the source code by hand, we've decide to create a component library built on top of MUI and host on our local registry. The issue is that when we use the components, they are stuck to the default palette and refuse to update to the one our apps are providing. (i.e., if our app theme primary colour was red, all of the MUI components in our app would be red apart from any from our own library which remain the default blue). In addition, our library does not adapt to light/dark mode changes (forever stuck on the light mode style).

I've checked that there isn't another rogue <ThemeProvider /> in my app unintentionally providing the default theme (there is not). And I've added @mui/material to the peer dependencies to my library (and also DevDependencies so TypeScript stops complaining about unresolved dependencies). I've also told my libraries Vite config to externalise @mui/material. Nothing seems to be out of the ordinary but I cannot understand why the components from the library are not using the theme provided by the app.

I've attached what one of my built ESM components looks like in case anyone sports anything wrong

import { jsx } from "react/jsx-runtime";
import InfoIcon from "@mui/icons-material/Info";
import IconButton from "@mui/material/IconButton";
import { useCallback } from "react";
import useNoti from "../hooks/useNoti.mjs";
function InfoButton(props) {
  const { addNoti } = useNoti();
  const handleClick = useCallback(() => {
    addNoti(props.info ?? "", { ...props.options, variant: "info" });
  }, [addNoti, props.info, props.options]);
  return /* @__PURE__ */ jsx(
    IconButton,
    {
      onClick: handleClick,
      sx: props.info ? {} : { visibility: "hidden" },
      tabIndex: -1,
      children: /* @__PURE__ */ jsx(InfoIcon, { color: "info" })
    }
  );
}
export {
  InfoButton as default
};

I've also attached my vite.config.ts for the same reason:

import react from '@vitejs/plugin-react'
import { readFileSync } from 'fs';
import { glob } from "glob";
import { resolve } from 'path'
import { fileURLToPath } from 'url';
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'

const packageJson = JSON.parse(
  readFileSync(resolve(__dirname, 'package.json'), 'utf-8')
)

// Get all peer dependencies
const peerDeps = Object.keys(packageJson.peerDependencies || {})

console.log(peerDeps)

// Create external matcher
const external = [
  ...peerDeps,
  'react/jsx-runtime',
  'react/jsx-dev-runtime',
  // Match all subpath imports from peer dependencies
  new RegExp(`^(${peerDeps.map(dep => dep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')})(/.*)?$`)
]

export default defineConfig({
  plugins: [
    react({
      jsxRuntime: 'automatic',
    }),
    dts({
      outDir: "dist/types",
      insertTypesEntry: true,
      include: ['src/**/*'],
      exclude: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/**/*.stories.tsx']
    })
  ],
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: '@atl/ui',
    },
    rollupOptions: {
      external, // [/node_modules/],
      input: Object.fromEntries(
        glob.sync('src/**/*.{ts,tsx}', {
          ignore: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/**/*.stories.tsx']
        }).map(file => {
          // Remove src/ prefix and file extension for entry key
          const filename = file.replace(/^src[/|\\]/, '').replace(/\.[^.]+$/, '');
          // Provide absolute path for entry value
          const path = fileURLToPath(new URL(file, import.meta.url))
          return [filename, path]
        })
      ),
      output: [
        {
          format: 'es',
          dir: 'dist/esm',
          entryFileNames: '[name].mjs',
          preserveModules: true,
          preserveModulesRoot: 'src',
          interop: 'auto',
          generatedCode: {
            symbols: true
          }
        },
        {
          format: 'cjs',
          dir: 'dist/cjs',
          entryFileNames: '[name].cjs',
          preserveModules: true,
          preserveModulesRoot: 'src',
          exports: 'named',
          interop: 'auto',
          generatedCode: {
            symbols: true
          }
        }
      ]
    },
    sourcemap: false,
    emptyOutDir: true,
    minify: false,
  }
})
Your environment
npx @mui/envinfo

System:
OS: Windows 11 10.0.26200
Binaries:
Node: 24.13.0 - C:\Program Files\nodejs\node.EXE
npm: 11.5.1 - C:\Program Files\nodejs\npm.CMD
Browsers:
Chrome: 144.0.7559.110
Edge: Chromium (140.0.3485.54)
npmPackages:
@emotion/react: 11.14.0
@emotion/styled: 11.14.1
@mui/core-downloads-tracker: 7.3.7
@mui/icons-material: 7.3.7
@mui/material: 7.3.7
@mui/material-nextjs: 7.3.7
@mui/private-theming: 7.3.7
@mui/styled-engine: 7.3.7
@mui/system: 7.3.7
@mui/types: 7.4.10
@mui/utils: 7.3.7
@mui/x-data-grid: 8.26.0
@mui/x-date-pickers: 8.26.0
@mui/x-internals: 8.26.0
@mui/x-virtualizer: 0.3.3
@toolpad/core: 0.16.0
@toolpad/utils: 0.16.0
@types/react: ^19.1.8 => 19.2.10
react: 19.2.0
react-dom: 19.2.0
typescript: ^5.8.3 => 5.9.3

Search keywords: theme

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the attached built ESM component and vite.config.ts, then inspect the package's peerDependencies and the reported @mui/material 7.3.7 setup. Reproduce the theme behavior with the reported React and MUI versions; done means library components follow the consuming app's palette and light/dark mode.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript, vite
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.