diff --git a/docs/src/pages/components/portal/portal.md b/docs/src/pages/components/portal/portal.md
index fe79e32f7ba4d5..4b9eab5d93f175 100644
--- a/docs/src/pages/components/portal/portal.md
+++ b/docs/src/pages/components/portal/portal.md
@@ -13,7 +13,7 @@ The children of the portal component will be appended to the `container` specifi
The component is used internally by the [`Modal`](/components/modal/) and [`Popper`](/components/popper/) components.
On the server, the content won't be rendered.
-You have to wait for the client side hydration to see the children.
+You have to wait for the client-side hydration to see the children.
## Simple Portal
diff --git a/docs/src/pages/components/use-media-query/ServerSide.js b/docs/src/pages/components/use-media-query/ServerSide.js
index b55fd899542aac..de67bacbaf18bb 100644
--- a/docs/src/pages/components/use-media-query/ServerSide.js
+++ b/docs/src/pages/components/use-media-query/ServerSide.js
@@ -1,28 +1,39 @@
import React from 'react';
import mediaQuery from 'css-mediaquery';
import { ThemeProvider } from '@material-ui/styles';
-import useMediaQueryTheme from '@material-ui/core/useMediaQuery';
+import useMediaQuery from '@material-ui/core/useMediaQuery';
function MyComponent() {
- const matches = useMediaQueryTheme('@media (min-width:600px)');
+ const matches = useMediaQuery('(min-width:600px)');
- return {`@media (min-width:600px) matches: ${matches}`};
+ return {`(min-width:600px) matches: ${matches}`};
}
export default function ServerSide() {
- // Use https://github.com/ericf/css-mediaquery as ponyfill.
const ssrMatchMedia = query => ({
+ // Use https://github.com/ericf/css-mediaquery as ponyfill.
matches: mediaQuery.match(query, {
// The estimated CSS width of the browser.
// For the sake of this demo, we are using a fixed value.
- // In production, you can look into client-hint https://caniuse.com/#search=client%20hint
- // or user-agent resolution.
+ //
+ // In production, you can leverage:
+ //
+ // - Client hints. You can ask the client to send your server its width.
+ // Be aware that this feature is not supported everywhere: https://caniuse.com/#search=client%20hint.
+ // - User-agent. You can parse the user agent of the client, then convert the data to a
+ // is mobile or is desktop variable, and finally, guess the most likely screen width of the client.
width: 800,
}),
});
return (
-
+
);
diff --git a/docs/src/pages/components/use-media-query/SimpleMediaQuery.tsx b/docs/src/pages/components/use-media-query/SimpleMediaQuery.tsx
new file mode 100644
index 00000000000000..4c3bf0e13fec7a
--- /dev/null
+++ b/docs/src/pages/components/use-media-query/SimpleMediaQuery.tsx
@@ -0,0 +1,8 @@
+import React from 'react';
+import useMediaQuery from '@material-ui/core/useMediaQuery';
+
+export default function SimpleMediaQuery() {
+ const matches = useMediaQuery('(min-width:600px)');
+
+ return {`(min-width:600px) matches: ${matches}`};
+}
diff --git a/docs/src/pages/components/use-media-query/use-media-query.md b/docs/src/pages/components/use-media-query/use-media-query.md
index 14eb4744d7a57d..fbfac9090a0cb8 100644
--- a/docs/src/pages/components/use-media-query/use-media-query.md
+++ b/docs/src/pages/components/use-media-query/use-media-query.md
@@ -11,8 +11,7 @@ Some of the key features:
- ⚛️ It has an idiomatic React API.
- 🚀 It's performant, it observes the document to detect when its media queries change, instead of polling the values periodically.
- 📦 [1 kB gzipped](/size-snapshot).
-- 💄 It's an alternative to react-responsive and react-media that aims for simplicity.
-- 🤖 It supports Server-side rendering.
+- 🤖 It supports server-side rendering.
## Simple media query
@@ -39,19 +38,68 @@ function MyComponent() {
{{"demo": "pages/components/use-media-query/ThemeHelper.js"}}
+Alternatively, you can use a callback function, accepting the theme as a first argument:
+
+```jsx
+import useMediaQuery from '@material-ui/core/useMediaQuery';
+
+function MyComponent() {
+ const matches = useMediaQuery(theme => theme.breakpoints.up('sm'));
+
+ return {`theme.breakpoints.up('sm') matches: ${matches}`};
+}
+```
+
+⚠️ There is **no default** theme support, you have to inject it in a parent theme provider.
+
## Using JavaScript syntax
-[json2mq](https://github.com/akiran/json2mq) is used to generate media query string from a JavaScript object.
+You can use [json2mq](https://github.com/akiran/json2mq) to generate media query string from a JavaScript object.
{{"demo": "pages/components/use-media-query/JavaScriptMedia.js", "defaultCodeOpen": true}}
## Server-side rendering
-An implementation of [matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) is required on the server, we recommend using [css-mediaquery](https://github.com/ericf/css-mediaquery).
-We also encourage the usage of the `useMediaQueryTheme` version of the hook that fetches properties from the theme. This way, you can provide a `ssrMatchMedia` option once for all your React tree.
+An implementation of [matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) is required on the server.
+We recommend using [css-mediaquery](https://github.com/ericf/css-mediaquery) to emulate it.
{{"demo": "pages/components/use-media-query/ServerSide.js"}}
+⚠️ Server-side rendering and client-side media queries are fundamentally at odds.
+Be aware of the tradeoff. The support can only be partial.
+
+Try relying on client-side CSS media queries first.
+For instance, you could use:
+
+- [``](/system/display/#hiding-elements)
+- [``](/components/hidden/#css)
+- or [`themes.breakpoints.up(x)`](/customization/breakpoints/#css-media-queries)
+
+## Testing
+
+Similar to the server-side case, you need an implementation of [matchMedia](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) in your test environment.
+
+For instance, [jsdom doesn't support it yet](https://github.com/jsdom/jsdom/blob/master/test/web-platform-tests/to-upstream/html/browsers/the-window-object/window-properties-dont-upstream.html). You should polyfill it.
+We recommend using [css-mediaquery](https://github.com/ericf/css-mediaquery) to emulate it.
+
+```js
+import mediaQuery from 'css-mediaquery';
+
+function createMatchMedia(width) {
+ return query => ({
+ matches: mediaQuery.match(query, { width }),
+ addListener: () => {},
+ removeListener: () => {},
+ });
+}
+
+describe('MyTests', () => {
+ beforeAll(() => {
+ window.matchMedia = createMatchMedia(window.innerWidth);
+ });
+});
+```
+
## Migrating from `withWidth()`
The `withWidth()` higher-order component injects the screen width of the page.
@@ -84,7 +132,7 @@ function useWidth() {
#### Arguments
-1. `query` (*String*): A string representing the media query to handle.
+1. `query` (*String* | *Function*): A string representing the media query to handle or a callback function accepting the theme (in the context) that returns a string.
2. `options` (*Object* [optional]):
- `options.defaultMatches` (*Boolean* [optional]):
As `window.matchMedia()` is unavailable on the server,
@@ -97,7 +145,7 @@ function useWidth() {
- `options.ssrMatchMedia` (*Function* [optional]) You might want to use an heuristic to approximate
the screen of the client browser.
For instance, you could be using the user-agent or the client-hint https://caniuse.com/#search=client%20hint.
- You can provide a global ponyfill using [`custom properties`](/customization/globals/#default-props) on the theme. Check the [server-side rendering example](#server-side-rendering).
+ You can provide a global ponyfill using [`custom props`](/customization/globals/#default-props) on the theme. Check the [server-side rendering example](#server-side-rendering).
#### Returns
diff --git a/docs/src/pages/styles/advanced/advanced.md b/docs/src/pages/styles/advanced/advanced.md
index 8439d9622aa3f6..ff966d7639b3bf 100644
--- a/docs/src/pages/styles/advanced/advanced.md
+++ b/docs/src/pages/styles/advanced/advanced.md
@@ -585,7 +585,7 @@ If you are using Server-Side Rendering (SSR), you should pass the nonce in the `
```
Then, you must pass this nonce to JSS so it can add it to subsequent `