diff --git a/packages/mui-material/src/useMediaQuery/index.d.ts b/packages/mui-material/src/useMediaQuery/index.d.ts
index 189cf6a41d036a..534d0663384e7f 100644
--- a/packages/mui-material/src/useMediaQuery/index.d.ts
+++ b/packages/mui-material/src/useMediaQuery/index.d.ts
@@ -1,2 +1,11 @@
-export { default } from '@mui/system/useMediaQuery';
+import { UseMediaQueryOptions } from '@mui/system/useMediaQuery';
+import { Theme } from '../styles/createTheme';
+
export * from '@mui/system/useMediaQuery';
+
+declare function useMediaQuery(
+ queryInput: string | ((theme: Theme) => string),
+ options?: UseMediaQueryOptions,
+): boolean;
+
+export default useMediaQuery;
diff --git a/packages/mui-material/src/useMediaQuery/index.js b/packages/mui-material/src/useMediaQuery/index.js
index ebc567714f0478..3773d6445a45d3 100644
--- a/packages/mui-material/src/useMediaQuery/index.js
+++ b/packages/mui-material/src/useMediaQuery/index.js
@@ -1 +1,6 @@
-export { default } from '@mui/system/useMediaQuery';
+import { unstable_createUseMediaQuery } from '@mui/system/useMediaQuery';
+import THEME_ID from '../styles/identifier';
+
+const useMediaQuery = unstable_createUseMediaQuery({ themeId: THEME_ID });
+
+export default useMediaQuery;
diff --git a/packages/mui-material/src/useMediaQuery/useMediaQuery.test.js b/packages/mui-material/src/useMediaQuery/useMediaQuery.test.js
index d5dc1530998c74..2f1059ef72926c 100644
--- a/packages/mui-material/src/useMediaQuery/useMediaQuery.test.js
+++ b/packages/mui-material/src/useMediaQuery/useMediaQuery.test.js
@@ -11,7 +11,7 @@ import mediaQuery from 'css-mediaquery';
import { expect } from 'chai';
import { stub } from 'sinon';
import useMediaQuery from '@mui/material/useMediaQuery';
-import { ThemeProvider } from '@mui/material/styles';
+import { THEME_ID, ThemeProvider, createTheme } from '@mui/material/styles';
const usesUseSyncExternalStore = React.useSyncExternalStore !== undefined;
const matchMediaInstances = new Map();
@@ -344,6 +344,40 @@ describe('useMediaQuery', () => {
});
});
+ describe('theme scoping', () => {
+ it('should work with theme scoping', () => {
+ function MyComponent() {
+ const matches = useMediaQuery((theme) => theme.breakpoints.up('xl'));
+
+ return {`${matches}`};
+ }
+
+ function Test() {
+ const ssrMatchMedia = (query) => ({
+ matches: mediaQuery.match(query, {
+ width: 3000,
+ }),
+ });
+
+ return (
+
+
+
+ );
+ }
+
+ const { container } = renderToString();
+
+ expect(container.firstChild).to.have.text('true');
+ });
+ });
+
describe('warnings', () => {
it('warns on invalid `query` argument', () => {
function MyComponent() {
diff --git a/packages/mui-system/src/useMediaQuery/useMediaQuery.ts b/packages/mui-system/src/useMediaQuery/useMediaQuery.ts
index 0c4bf8c9e5e4e1..d3da7b61287469 100644
--- a/packages/mui-system/src/useMediaQuery/useMediaQuery.ts
+++ b/packages/mui-system/src/useMediaQuery/useMediaQuery.ts
@@ -117,53 +117,64 @@ function useMediaQueryNew(
return match;
}
-export default function useMediaQuery(
- queryInput: string | ((theme: Theme) => string),
- options: UseMediaQueryOptions = {},
-): boolean {
- const theme = useTheme();
- // Wait for jsdom to support the match media feature.
- // All the browsers MUI support have this built-in.
- // This defensive check is here for simplicity.
- // Most of the time, the match media logic isn't central to people tests.
- const supportMatchMedia =
- typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';
- const {
- defaultMatches = false,
- matchMedia = supportMatchMedia ? window.matchMedia : null,
- ssrMatchMedia = null,
- noSsr = false,
- } = getThemeProps({ name: 'MuiUseMediaQuery', props: options, theme });
-
- if (process.env.NODE_ENV !== 'production') {
- if (typeof queryInput === 'function' && theme === null) {
- console.error(
- [
- 'MUI: The `query` argument provided is invalid.',
- 'You are providing a function without a theme in the context.',
- 'One of the parent elements needs to use a ThemeProvider.',
- ].join('\n'),
- );
+// eslint-disable-next-line @typescript-eslint/naming-convention
+export function unstable_createUseMediaQuery(params: { themeId?: string } = {}) {
+ const { themeId } = params;
+ return function useMediaQuery(
+ queryInput: string | ((theme: Theme) => string),
+ options: UseMediaQueryOptions = {},
+ ): boolean {
+ let theme = useTheme();
+ if (theme && themeId) {
+ theme = (theme as Record)[themeId] || theme;
+ }
+ // Wait for jsdom to support the match media feature.
+ // All the browsers MUI support have this built-in.
+ // This defensive check is here for simplicity.
+ // Most of the time, the match media logic isn't central to people tests.
+ const supportMatchMedia =
+ typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';
+ const {
+ defaultMatches = false,
+ matchMedia = supportMatchMedia ? window.matchMedia : null,
+ ssrMatchMedia = null,
+ noSsr = false,
+ } = getThemeProps({ name: 'MuiUseMediaQuery', props: options, theme });
+
+ if (process.env.NODE_ENV !== 'production') {
+ if (typeof queryInput === 'function' && theme === null) {
+ console.error(
+ [
+ 'MUI: The `query` argument provided is invalid.',
+ 'You are providing a function without a theme in the context.',
+ 'One of the parent elements needs to use a ThemeProvider.',
+ ].join('\n'),
+ );
+ }
}
- }
-
- let query = typeof queryInput === 'function' ? queryInput(theme) : queryInput;
- query = query.replace(/^@media( ?)/m, '');
-
- const useMediaQueryImplementation =
- maybeReactUseSyncExternalStore !== undefined ? useMediaQueryNew : useMediaQueryOld;
- const match = useMediaQueryImplementation(
- query,
- defaultMatches,
- matchMedia,
- ssrMatchMedia,
- noSsr,
- );
-
- if (process.env.NODE_ENV !== 'production') {
- // eslint-disable-next-line react-hooks/rules-of-hooks
- React.useDebugValue({ query, match });
- }
- return match;
+ let query = typeof queryInput === 'function' ? queryInput(theme) : queryInput;
+ query = query.replace(/^@media( ?)/m, '');
+
+ const useMediaQueryImplementation =
+ maybeReactUseSyncExternalStore !== undefined ? useMediaQueryNew : useMediaQueryOld;
+ const match = useMediaQueryImplementation(
+ query,
+ defaultMatches,
+ matchMedia,
+ ssrMatchMedia,
+ noSsr,
+ );
+
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ React.useDebugValue({ query, match });
+ }
+
+ return match;
+ };
}
+
+const useMediaQuery = unstable_createUseMediaQuery();
+
+export default useMediaQuery;