diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3c67a6ed490bce..d9da5f40aba9ed 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -182,14 +182,20 @@ jobs:
- *restore_yarn_cache
- *install_js
- run:
- name: Can we generate the material-ui build?
+ name: Can we generate the @material-ui/core build?
command: cd packages/material-ui && yarn build
+ - run:
+ name: Can we generate the @material-ui/styles build?
+ command: cd packages/material-ui-styles && yarn build
+ - run:
+ name: Can we generate the @material-ui/utils build?
+ command: cd packages/material-ui-utils && yarn build
- run:
name: Can we build the docs?
command: yarn docs:build
- run:
name: Is the size acceptable?
- command: yarn size
+ command: yarn lerna bootstrap && yarn size
test_browser:
<<: *defaults
steps:
diff --git a/.eslintignore b/.eslintignore
index 0777d22a230b81..68cab7b27ba9b9 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -6,8 +6,6 @@
/examples/create-react-app-with-flow/flow
/examples/create-react-app-with-flow/flow-typed
/examples/gatsby/public
-/flow
-/flow-typed
/packages/material-ui-codemod/lib
/packages/material-ui-codemod/src/*/*.test
/packages/material-ui-codemod/src/*/*.test.js
diff --git a/.size-limit.js b/.size-limit.js
index 3d999b239eb9b1..feffa88a5c1e0f 100644
--- a/.size-limit.js
+++ b/.size-limit.js
@@ -19,16 +19,22 @@ module.exports = [
limit: '18.5 KB',
},
{
- name: 'The size of all the material-ui modules.',
+ name: 'The size of the @material-ui/core modules',
webpack: true,
path: 'packages/material-ui/build/index.js',
limit: '94.1 KB',
},
+ {
+ name: 'The size of the @material-ui/styles modules',
+ webpack: true,
+ path: 'packages/material-ui-styles/build/index.js',
+ limit: '14.9 KB',
+ },
{
name: 'The main docs bundle',
webpack: false,
path: main.path,
- limit: '185 KB',
+ limit: '190 KB',
},
{
name: 'The docs home page',
diff --git a/BACKERS.md b/BACKERS.md
index 5a0373edd5e054..2bd7760ce3085b 100644
--- a/BACKERS.md
+++ b/BACKERS.md
@@ -68,7 +68,7 @@ via [Patreon](https://www.patreon.com/oliviertassinari)
| Avétis KAZARIAN | Withinpixels | SIM KIM SIA | Renaud Bompuis | Yaron Malin |
| Arvanitis Panagiotis | Jesse Weigel | Bogdan Mihai Nicolae | Dung Tran | Kyle Pennell |
| Kai Mit Pansen | Eric Nagy | Karens Grigorjancs | Mohamed Turco | Haroun Serang |
-| Antonio Seveso | Ali Akhavan | Bruno Winck | Alessandro Annini |
+| Antonio Seveso | Ali Akhavan | Bruno Winck | Alessandro Annini | Victor Irzak |
via [OpenCollective](https://opencollective.com/material-ui)
diff --git a/babel.config.js b/babel.config.js
index bdc42ca75b9c14..f727e37ec2bd1d 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -27,6 +27,14 @@ if (process.env.BABEL_ENV === 'es') {
];
}
+const defaultAlias = {
+ '@material-ui/core': './packages/material-ui/src',
+ '@material-ui/icons': './packages/material-ui-icons/src',
+ '@material-ui/lab': './packages/material-ui-lab/src',
+ '@material-ui/styles': './packages/material-ui-styles/src',
+ '@material-ui/utils': './packages/material-ui-utils/src',
+};
+
module.exports = {
presets: defaultPresets.concat(['@babel/preset-react']),
plugins: [
@@ -42,6 +50,18 @@ module.exports = {
'@babel/plugin-transform-runtime',
],
env: {
+ test: {
+ sourceMaps: 'both',
+ plugins: [
+ [
+ 'babel-plugin-module-resolver',
+ {
+ root: ['./'],
+ alias: defaultAlias,
+ },
+ ],
+ ],
+ },
coverage: {
plugins: [
'babel-plugin-istanbul',
@@ -49,10 +69,7 @@ module.exports = {
'babel-plugin-module-resolver',
{
root: ['./'],
- alias: {
- '@material-ui/core': './packages/material-ui/src',
- '@material-ui/icons': './packages/material-ui-icons/src',
- },
+ alias: defaultAlias,
},
],
],
@@ -76,10 +93,8 @@ module.exports = {
'babel-plugin-module-resolver',
{
alias: {
- '@material-ui/core': './packages/material-ui/src',
+ ...defaultAlias,
'@material-ui/docs': './packages/material-ui-docs/src',
- '@material-ui/icons': './packages/material-ui-icons/src',
- '@material-ui/lab': './packages/material-ui-lab/src',
docs: './docs',
modules: './modules',
pages: './pages',
@@ -97,10 +112,8 @@ module.exports = {
'babel-plugin-module-resolver',
{
alias: {
- '@material-ui/core': './packages/material-ui/src',
+ ...defaultAlias,
'@material-ui/docs': './packages/material-ui-docs/src',
- '@material-ui/icons': './packages/material-ui-icons/src',
- '@material-ui/lab': './packages/material-ui-lab/src',
docs: './docs',
modules: './modules',
pages: './pages',
@@ -160,20 +173,5 @@ module.exports = {
],
],
},
- test: {
- sourceMaps: 'both',
- plugins: [
- [
- 'babel-plugin-module-resolver',
- {
- root: ['./'],
- alias: {
- '@material-ui/core': './packages/material-ui/src',
- '@material-ui/icons': './packages/material-ui-icons/src',
- },
- },
- ],
- ],
- },
},
};
diff --git a/crowdin.yml b/crowdin.yml
index 272ffd1325a29e..2d17c709d3f54b 100644
--- a/crowdin.yml
+++ b/crowdin.yml
@@ -2,5 +2,5 @@ files:
- source: /docs/src/pages/**/*.md
ignore:
- /**/%file_name%-%two_letters_code%.md
- - /docs/src/pages/page-layout-examples/**/*
+ - /docs/src/pages/getting-started/page-layout-examples/**/*
translation: /%original_path%/%file_name%-%two_letters_code%.%file_extension%
diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js
index caae85c6ebc151..ec6aa732a0873f 100644
--- a/docs/src/modules/components/AppTableOfContents.js
+++ b/docs/src/modules/components/AppTableOfContents.js
@@ -4,6 +4,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import Link from 'docs/src/modules/components/Link';
import marked from 'marked';
+import warning from 'warning';
import throttle from 'lodash/throttle';
import EventListener from 'react-event-listener';
import { withStyles } from '@material-ui/core/styles';
@@ -22,6 +23,10 @@ renderer.heading = (text, level) => {
children: [],
});
} else if (level === 3) {
+ if (!itemsServer[itemsServer.length - 1]) {
+ throw new Error(`Missing parent level for: ${text}`);
+ }
+
itemsServer[itemsServer.length - 1].children.push({
text,
level,
@@ -61,6 +66,14 @@ const styles = theme => ({
},
});
+function checkDuplication(uniq, item) {
+ warning(!uniq[item.hash], `Duplicated table of content ${item.hash}`);
+
+ if (!uniq[item.hash]) {
+ uniq[item.hash] = true;
+ }
+}
+
class AppTableOfContents extends React.Component {
handleScroll = throttle(() => {
this.findActiveIndex();
@@ -80,8 +93,10 @@ class AppTableOfContents extends React.Component {
componentDidMount() {
this.itemsClient = [];
+ const uniq = {};
itemsServer.forEach(item2 => {
+ checkDuplication(uniq, item2);
this.itemsClient.push({
...item2,
node: document.getElementById(item2.hash),
@@ -89,6 +104,7 @@ class AppTableOfContents extends React.Component {
if (item2.children.length > 0) {
item2.children.forEach(item3 => {
+ checkDuplication(uniq, item3);
this.itemsClient.push({
...item3,
node: document.getElementById(item3.hash),
diff --git a/docs/src/modules/components/AppWrapper.js b/docs/src/modules/components/AppWrapper.js
index cd3fd1abe12440..df77ca9bd6728a 100644
--- a/docs/src/modules/components/AppWrapper.js
+++ b/docs/src/modules/components/AppWrapper.js
@@ -3,8 +3,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { MuiThemeProvider } from '@material-ui/core/styles';
-import JssProvider from 'react-jss/lib/JssProvider';
+import { ThemeProvider, StylesProvider } from '@material-ui/styles';
import { lightTheme, darkTheme, setPrismTheme } from '@material-ui/docs/MarkdownElement/prism';
import getPageContext, { updatePageContext } from 'docs/src/modules/styles/getPageContext';
import GoogleAnalytics from 'docs/src/modules/components/GoogleAnalytics';
@@ -79,16 +78,17 @@ class AppWrapper extends React.Component {
const { pageContext } = this.state;
return (
-
-
+
{children}
-
-
+
+
);
}
}
diff --git a/docs/src/modules/components/Demo.js b/docs/src/modules/components/Demo.js
index 1348a91abf73f7..fa03648916b445 100644
--- a/docs/src/modules/components/Demo.js
+++ b/docs/src/modules/components/Demo.js
@@ -312,7 +312,7 @@ Demo.propTypes = {
demoOptions: PropTypes.object.isRequired,
githubLocation: PropTypes.string.isRequired,
index: PropTypes.number.isRequired,
- js: PropTypes.func.isRequired,
+ js: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
raw: PropTypes.string.isRequired,
};
diff --git a/docs/src/modules/components/DemoFrame.js b/docs/src/modules/components/DemoFrame.js
index 8d8af6b4509bc7..79e638cb28899b 100644
--- a/docs/src/modules/components/DemoFrame.js
+++ b/docs/src/modules/components/DemoFrame.js
@@ -7,9 +7,9 @@ import {
jssPreset,
MuiThemeProvider,
} from '@material-ui/core/styles';
+import { StylesProvider } from '@material-ui/styles';
import rtl from 'jss-rtl';
import Frame from 'react-frame-component';
-import JssProvider from 'react-jss/lib/JssProvider';
const styles = theme => ({
root: {
@@ -52,13 +52,13 @@ class DemoFrame extends React.Component {
const { children, classes, theme } = this.props;
const inIframe = this.state.ready ? (
-
+
{React.cloneElement(children, {
container: this.state.container,
})}
-
+
) : null;
return (
diff --git a/docs/src/modules/components/bootstrap.js b/docs/src/modules/components/bootstrap.js
new file mode 100644
index 00000000000000..adbc5803a69392
--- /dev/null
+++ b/docs/src/modules/components/bootstrap.js
@@ -0,0 +1,3 @@
+import { install } from '@material-ui/styles';
+
+install();
diff --git a/docs/src/modules/components/withRoot.js b/docs/src/modules/components/withRoot.js
index 72462554473830..b89b1c360d2367 100644
--- a/docs/src/modules/components/withRoot.js
+++ b/docs/src/modules/components/withRoot.js
@@ -2,6 +2,7 @@
import 'core-js/modules/es6.array.find-index';
import 'core-js/modules/es6.set';
+import './bootstrap';
import React from 'react';
import PropTypes from 'prop-types';
import find from 'lodash/find';
@@ -40,18 +41,21 @@ const pages = [
pathname: '/getting-started/usage',
},
{
- pathname: '/getting-started/supported-components',
- },
- {
- pathname: '/getting-started/supported-platforms',
+ pathname: '/getting-started/example-projects',
},
{
- pathname: '/getting-started/example-projects',
+ pathname: '/getting-started/page-layout-examples',
},
{
pathname: '/getting-started/faq',
title: 'Frequently Asked Questions',
},
+ {
+ pathname: '/getting-started/supported-components',
+ },
+ {
+ pathname: '/getting-started/supported-platforms',
+ },
{
pathname: '/getting-started/comparison',
title: 'Comparison With Other Libraries',
@@ -128,6 +132,22 @@ const pages = [
...findPages[0],
title: 'Component API',
},
+ {
+ pathname: '/css-in-js',
+ title: 'CSS in JS (experimental)',
+ children: [
+ {
+ pathname: '/css-in-js/basics',
+ },
+ {
+ pathname: '/css-in-js/advanced',
+ },
+ {
+ pathname: '/css-in-js/api',
+ title: 'API',
+ },
+ ],
+ },
{
pathname: '/customization',
children: [
@@ -185,18 +205,11 @@ const pages = [
pathname: '/guides/right-to-left',
title: 'Right-to-left',
},
- {
- pathname: '/guides/csp',
- title: 'Content Security Policy',
- },
],
},
{
pathname: '/premium-themes',
},
- {
- pathname: '/page-layout-examples',
- },
{
pathname: '/lab',
children: [
@@ -213,7 +226,10 @@ const pages = [
{
pathname: '/lab/toggle-button',
},
- findPages[2].children[1],
+ {
+ ...findPages[2].children[1],
+ title: 'API',
+ },
],
},
{
@@ -319,19 +335,22 @@ function withRoot(Component) {
}
const activePage = findActivePage(pages, { ...router, pathname });
+ // Add the strict mode back once the number of warnings is manageable.
+ // We might miss important warnings by keeping the strict mode 🌊🌊🌊.
+ //
+ //
+
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
}
}
diff --git a/docs/src/modules/styles/getPageContext.js b/docs/src/modules/styles/getPageContext.js
index 0f50f4c2623da9..91d15579cffae6 100644
--- a/docs/src/modules/styles/getPageContext.js
+++ b/docs/src/modules/styles/getPageContext.js
@@ -41,8 +41,8 @@ const theme = getTheme({
// Configure JSS
const jss = create({
- insertionPoint: 'insertion-point-jss',
plugins: [...jssPreset().plugins, rtl()],
+ insertionPoint: 'insertion-point-jss',
});
function createPageContext() {
diff --git a/docs/src/pages/css-in-js/advanced/StringTemplates.js b/docs/src/pages/css-in-js/advanced/StringTemplates.js
new file mode 100644
index 00000000000000..04e5095f80e1ae
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/StringTemplates.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import { jssPreset, StylesProvider, makeStyles } from '@material-ui/styles';
+import { create } from 'jss';
+import jssTemplate from 'jss-template';
+import Button from '@material-ui/core/Button';
+
+const jss = create({
+ plugins: [jssTemplate(), ...jssPreset().plugins],
+});
+
+const useStyles = makeStyles({
+ root: `
+ background: linear-gradient(45deg, #fe6b8b 30%, #ff8e53 90%);
+ border-radius: 3;
+ border: 0;
+ color: white;
+ height: 48px;
+ padding: 0 30px;
+ box-shadow: 0 3px 5px 2px rgba(255, 105, 135, 0.3);
+ `,
+});
+
+function Child() {
+ const classes = useStyles();
+ return String templates ;
+}
+
+function StringTemplates() {
+ return (
+
+
+
+ );
+}
+
+export default StringTemplates;
diff --git a/docs/src/pages/css-in-js/advanced/ThemeNesting.js b/docs/src/pages/css-in-js/advanced/ThemeNesting.js
new file mode 100644
index 00000000000000..90c203f6e8dc2d
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/ThemeNesting.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import { ThemeProvider, makeStyles } from '@material-ui/styles';
+import Button from '@material-ui/core/Button';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ background: theme.background,
+ border: 0,
+ borderRadius: 3,
+ boxShadow: theme.boxShadow,
+ color: 'white',
+ height: 48,
+ padding: '0 30px',
+ },
+}));
+
+function DeepChild() {
+ const classes = useStyles();
+
+ return Theme nesting ;
+}
+
+function Theme() {
+ return (
+
+
+
+
+
+ ({
+ ...outerTheme,
+ background: 'linear-gradient(45deg, #2196F3 30%, #21CBF3 90%)',
+ boxShadow: '0 3px 5px 2px rgba(33, 203, 243, .3)',
+ })}
+ >
+
+
+
+
+ );
+}
+
+export default Theme;
diff --git a/docs/src/pages/css-in-js/advanced/Theming.js b/docs/src/pages/css-in-js/advanced/Theming.js
new file mode 100644
index 00000000000000..b05fcc47781f7e
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/Theming.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import { ThemeProvider, makeStyles } from '@material-ui/styles';
+import Button from '@material-ui/core/Button';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ background: theme.background,
+ border: 0,
+ borderRadius: 3,
+ boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
+ color: 'white',
+ height: 48,
+ padding: '0 30px',
+ },
+}));
+
+function DeepChild() {
+ const classes = useStyles();
+
+ return Theming ;
+}
+
+function Theming() {
+ return (
+
+
+
+ );
+}
+
+export default Theming;
diff --git a/docs/src/pages/css-in-js/advanced/UseTheme.js b/docs/src/pages/css-in-js/advanced/UseTheme.js
new file mode 100644
index 00000000000000..80b11264184ca5
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/UseTheme.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { ThemeProvider, useTheme } from '@material-ui/styles';
+import Button from '@material-ui/core/Button';
+
+function DeepChild() {
+ const theme = useTheme();
+
+ return {`spacing ${theme.spacing}`} ;
+}
+
+function UseTheme() {
+ return (
+
+
+
+ );
+}
+
+export default UseTheme;
diff --git a/docs/src/pages/css-in-js/advanced/WithTheme.js b/docs/src/pages/css-in-js/advanced/WithTheme.js
new file mode 100644
index 00000000000000..fa90a27fa561e3
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/WithTheme.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { ThemeProvider, withTheme } from '@material-ui/styles';
+import Button from '@material-ui/core/Button';
+
+function DeepChildRaw(props) {
+ return {`spacing ${props.theme.spacing}`} ;
+}
+
+DeepChildRaw.propTypes = {
+ theme: PropTypes.object.isRequired,
+};
+
+const DeepChild = withTheme()(DeepChildRaw);
+
+function WithTheme() {
+ return (
+
+
+
+ );
+}
+
+export default WithTheme;
diff --git a/docs/src/pages/css-in-js/advanced/advanced.md b/docs/src/pages/css-in-js/advanced/advanced.md
new file mode 100644
index 00000000000000..92ba74e65a422b
--- /dev/null
+++ b/docs/src/pages/css-in-js/advanced/advanced.md
@@ -0,0 +1,313 @@
+# Advanced
+
+Advanced Usage.
+
+## Theming
+
+Add a `ThemeProvider` to the top level of your app to access the theme down the React's component tree. Then, you can access the theme object in the style functions.
+
+{{"demo": "pages/css-in-js/advanced/Theming.js"}}
+
+## Accessing the theme in a component
+
+You might need to access the theme variables inside your React components.
+
+### `useTheme` hook
+
+{{"demo": "pages/css-in-js/advanced/UseTheme.js"}}
+
+### `withTheme` HOC
+
+{{"demo": "pages/css-in-js/advanced/WithTheme.js"}}
+
+## Theme nesting
+
+You can nest multiple theme providers.
+This can be really useful when dealing with different area of your application that have distinct appearance from each other.
+
+{{"demo": "pages/css-in-js/advanced/ThemeNesting.js"}}
+
+## JSS plugins
+
+JSS uses the concept of plugins to extend its core, allowing people to cherry-pick the features they need.
+You pay the performance overhead for only what's you are using.
+All the plugins aren't available by default. We have added the following list:
+
+- [jss-global](http://cssinjs.org/jss-global/)
+- [jss-nested](http://cssinjs.org/jss-nested/)
+- [jss-camel-case](http://cssinjs.org/jss-camel-case/)
+- [jss-default-unit](http://cssinjs.org/jss-default-unit/)
+- [jss-vendor-prefixer](http://cssinjs.org/jss-vendor-prefixer/)
+- [jss-props-sort](http://cssinjs.org/jss-props-sort/)
+
+It's a subset of [jss-preset-default](http://cssinjs.org/jss-preset-default/).
+Of course, you are free to add a new plugin. Here is an example with the [jss-rtl](https://github.com/alitaheri/jss-rtl) plugin.
+
+```jsx
+import { create } from 'jss';
+import { StylesProvider, jssPreset } from '@material-ui/styles';
+import rtl from 'jss-rtl'
+
+const jss = create({
+ plugins: [...jssPreset().plugins, rtl()],
+});
+
+function App() {
+ return (
+
+ ...
+
+ );
+}
+
+export default App;
+```
+
+## String templates
+
+If you prefer using the CSS syntax, you can use the [jss-template](https://cssinjs.org/jss-template) plugin.
+
+```jsx
+const useStyles = makeStyles({
+ root: `
+ background: linear-gradient(45deg, #fe6b8b 30%, #ff8e53 90%);
+ border-radius: 3;
+ border: 0;
+ color: white;
+ height: 48px;
+ padding: 0 30px;
+ box-shadow: 0 3px 5px 2px rgba(255, 105, 135, 0.3);
+ `,
+});
+```
+
+{{"demo": "pages/css-in-js/advanced/StringTemplates.js"}}
+
+## CSS injection order
+
+The CSS injected by Material-UI to style a component has the highest specificity possible as the ` ` is injected at the bottom of the `` to ensure the components always render correctly.
+
+You might, however, also want to override these styles, for example with styled-components.
+If you are experiencing a CSS injection order issue, JSS [provides a mechanism](https://github.com/cssinjs/jss/blob/master/docs/setup.md#specify-dom-insertion-point) to handle this situation.
+By adjusting the placement of the `insertionPoint` within your HTML head you can [control the order](http://cssinjs.org/js-api/#attach-style-sheets-in-a-specific-order) that the CSS rules are applied to your components.
+
+### HTML comment
+
+The simplest approach is to add an HTML comment that determines where JSS will inject the styles:
+
+```jsx
+
+
+
+
+```
+
+```jsx
+import { create } from 'jss';
+import { StylesProvider, jssPreset } from '@material-ui/styles';
+
+const jss = create({
+ ...jssPreset(),
+ // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
+ insertionPoint: 'jss-insertion-point',
+});
+
+function App() {
+ return ... ;
+}
+
+export default App;
+```
+
+### Other HTML element
+
+[Create React App](https://github.com/facebook/create-react-app) strips HTML comments when creating the production build.
+To get around the issue, you can provide a DOM element (other than a comment) as the JSS insertion point.
+
+For example, a `` element:
+
+```jsx
+
+
+
+
+```
+
+```jsx
+import { create } from 'jss';
+import { StylesProvider, jssPreset } from '@material-ui/styles';
+
+const jss = create({
+ ...jssPreset(),
+ // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
+ insertionPoint: document.getElementById('jss-insertion-point'),
+});
+
+function App() {
+ return ... ;
+}
+
+export default App;
+```
+
+### JS createComment
+
+codesandbox.io prevents the access to the `` element.
+To get around the issue, you can use the JavaScript `document.createComment()` API:
+
+```jsx
+import { create } from 'jss';
+import { StylesProvider, jssPreset } from '@material-ui/styles';
+
+const styleNode = document.createComment('jss-insertion-point');
+document.head.insertBefore(styleNode, document.head.firstChild);
+
+const jss = create({
+ ...jssPreset(),
+ // We define a custom insertion point that JSS will look for injecting the styles in the DOM.
+ insertionPoint: 'jss-insertion-point',
+});
+
+function App() {
+ return ... ;
+}
+
+export default App;
+```
+
+## Server Side Rendering
+
+## Class names
+
+You may have noticed that the class names generated by our styling solution are **non-deterministic**,
+so you can't rely on them to stay the same.
+The class names are generator by [our class name generator](/css-in-js/api/#creategenerateclassname--options----class-name-generator)
+Let's take the following style as an example:
+
+```jsx
+const useStyles = makeStyles({
+ root: {
+ opacity: 1,
+ },
+}, {
+ name: 'AppBar',
+});
+```
+
+It will generate a `AppBar-root-12` class name. However, the following CSS won't work:
+
+```css
+.AppBar-root-12 {
+ opacity: 0.6;
+}
+```
+
+You have to use the `classes` property of a component to override them.
+Thanks to the non-deterministic nature of our class names, we
+can implement optimizations for development and production.
+They are easy to debug in development and as short as possible in production:
+
+- In **development**, the class name will be: `.AppBar-root-12`, following this logic:
+
+```js
+const sheetName = 'AppBar';
+const ruleName = 'root';
+const identifier = 12;
+
+const className = `${sheetName}-${ruleName}-${identifier}`;
+```
+
+- In **production**, the class name will be: `.jss12`, following this logic:
+
+```js
+const productionPrefix = 'jss';
+const identifier = 12;
+
+const className = `${productionPrefix}-${identifier}`;
+```
+
+If you don't like this default behavior, you can change it.
+JSS relies on the concept of [class name generator](http://cssinjs.org/js-api/#generate-your-own-class-names).
+
+## Global CSS
+
+We provide an option to make the class names **deterministic** with the [`dangerouslyUseGlobalCSS`](/css-in-js/api/#creategenerateclassname--options----class-name-generator) option. When turned on, the class names will look like this:
+
+- development: `.AppBar-root`
+- production: `.AppBar-root`
+
+⚠️ **Be cautious when using `dangerouslyUseGlobalCSS`.**
+We provide this option as an escape hatch for prototyping.
+Relying on it for code running in production has the following implications:
+
+- Global CSS is inherently fragile. People use strict methodologies like [BEM](http://getbem.com/introduction/) to workaround the issue.
+- It's harder to keep track of `classes` API changes.
+
+⚠️ When using `dangerouslyUseGlobalCSS` standalone (without Material-UI), you should name your style sheets using the `options` parameter:
+
+```jsx
+// Hook
+const useStyles = makeStyles(styles, { name: 'button' });
+
+// Styled-components
+const Button = styled(styles, { name: 'button' })(ButtonBase);
+
+// Higher-order component
+const Button = withStyles(styles, { name: 'button' })(ButtonBase);
+
+// Render props
+const Styled = createStyled(styles, { name: 'button' });
+```
+
+## Content Security Policy (CSP)
+
+### What is CSP and why is it useful?
+
+Basically, CSP mitigates cross-site scripting (XSS) attacks by requiring developers to whitelist the sources their assets are retrieved from. This list is returned as a header from the server. For instance, say you have a site hosted at `https://example.com` the CSP header `default-src: 'self';` will allow all assets that are located at `https://example.com/*` and deny all others. If there is a section of your website that is vulnerable to XSS where unescaped user input is displayed, an attacker could input something like:
+
+```
+
+```
+
+This vulnerability would allow the attacker to execute anything. However, with a secure CSP header, the browser will not load this script.
+
+You can read more about CSP [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
+
+### How does one implement CSP?
+
+In order to use CSP with Material-UI (and JSS), you need to use a nonce. A nonce is a randomly generated string that is only used once, therefore you need to add a server middleware to generate one on each request. JSS has a [great tutorial](https://github.com/cssinjs/jss/blob/master/docs/csp.md) on how to achieve this with Express and React Helmet. For a basic rundown, continue reading.
+
+A CSP nonce is a Base 64 encoded string. You can generate one like this:
+
+```js
+import uuidv4 from 'uuid/v4';
+
+const nonce = new Buffer(uuidv4()).toString('base64');
+```
+
+It is very important you use UUID version 4, as it generates an **unpredictable** string.
+You then apply this nonce to the CSP header. A CSP header might look like this with the nonce applied:
+
+```js
+header('Content-Security-Policy')
+ .set(`default-src 'self'; style-src: 'self' 'nonce-${nonce}';`);
+```
+
+If you are using Server Side Rendering (SSR), you should pass the nonce in the `