diff --git a/docs/src/pages/guides/interoperability/EmotionCSS.js b/docs/src/pages/guides/interoperability/EmotionCSS.js index 854e0333c39d85..4d68337a731a4f 100644 --- a/docs/src/pages/guides/interoperability/EmotionCSS.js +++ b/docs/src/pages/guides/interoperability/EmotionCSS.js @@ -1,26 +1,22 @@ /** @jsx jsx */ import { jsx, css } from '@emotion/core'; -import Button from '@material-ui/core/Button'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; export default function EmotionCSS() { return ( -
- - -
+ /> + ); } diff --git a/docs/src/pages/guides/interoperability/EmotionCSS.tsx b/docs/src/pages/guides/interoperability/EmotionCSS.tsx index 854e0333c39d85..4d68337a731a4f 100644 --- a/docs/src/pages/guides/interoperability/EmotionCSS.tsx +++ b/docs/src/pages/guides/interoperability/EmotionCSS.tsx @@ -1,26 +1,22 @@ /** @jsx jsx */ import { jsx, css } from '@emotion/core'; -import Button from '@material-ui/core/Button'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; export default function EmotionCSS() { return ( -
- - -
+ /> + ); } diff --git a/docs/src/pages/guides/interoperability/EmotionTheme.js b/docs/src/pages/guides/interoperability/EmotionTheme.js deleted file mode 100644 index 392d92994337b8..00000000000000 --- a/docs/src/pages/guides/interoperability/EmotionTheme.js +++ /dev/null @@ -1,48 +0,0 @@ -/** @jsx jsx */ -import { jsx, css } from '@emotion/core'; -import Button from '@material-ui/core/Button'; -import { ThemeProvider } from 'emotion-theming'; -import { - createMuiTheme, - ThemeProvider as MuiThemeProvider, - darken, -} from '@material-ui/core/styles'; - -const customTheme = createMuiTheme({ - palette: { - primary: { - main: '#6772e5', - }, - }, -}); - -export default function EmotionTheme() { - return ( - - - - - - - ); -} diff --git a/docs/src/pages/guides/interoperability/EmotionTheme.tsx b/docs/src/pages/guides/interoperability/EmotionTheme.tsx deleted file mode 100644 index 392d92994337b8..00000000000000 --- a/docs/src/pages/guides/interoperability/EmotionTheme.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/** @jsx jsx */ -import { jsx, css } from '@emotion/core'; -import Button from '@material-ui/core/Button'; -import { ThemeProvider } from 'emotion-theming'; -import { - createMuiTheme, - ThemeProvider as MuiThemeProvider, - darken, -} from '@material-ui/core/styles'; - -const customTheme = createMuiTheme({ - palette: { - primary: { - main: '#6772e5', - }, - }, -}); - -export default function EmotionTheme() { - return ( - - - - - - - ); -} diff --git a/docs/src/pages/guides/interoperability/StyledComponents.js b/docs/src/pages/guides/interoperability/StyledComponents.js index 1b74604a38d6a3..71f3d0076ace56 100644 --- a/docs/src/pages/guides/interoperability/StyledComponents.js +++ b/docs/src/pages/guides/interoperability/StyledComponents.js @@ -1,24 +1,21 @@ import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; -import NoSsr from '@material-ui/core/NoSsr'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; -const StyledButton = styled(Button)` - background-color: #6772e5; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +const SliderCustomized = styled(Slider)` + color: #20b2aa; - &:hover { - background-color: #5469d4; + :hover { + color: #2e8b57; } `; export default function StyledComponents() { return ( - - - Customized - + + + + ); } diff --git a/docs/src/pages/guides/interoperability/StyledComponents.tsx b/docs/src/pages/guides/interoperability/StyledComponents.tsx index 1b74604a38d6a3..71f3d0076ace56 100644 --- a/docs/src/pages/guides/interoperability/StyledComponents.tsx +++ b/docs/src/pages/guides/interoperability/StyledComponents.tsx @@ -1,24 +1,21 @@ import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; -import NoSsr from '@material-ui/core/NoSsr'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; -const StyledButton = styled(Button)` - background-color: #6772e5; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +const SliderCustomized = styled(Slider)` + color: #20b2aa; - &:hover { - background-color: #5469d4; + :hover { + color: #2e8b57; } `; export default function StyledComponents() { return ( - - - Customized - + + + + ); } diff --git a/docs/src/pages/guides/interoperability/StyledComponentsDeep.js b/docs/src/pages/guides/interoperability/StyledComponentsDeep.js index f5446e973b4b32..d1f0130d956856 100644 --- a/docs/src/pages/guides/interoperability/StyledComponentsDeep.js +++ b/docs/src/pages/guides/interoperability/StyledComponentsDeep.js @@ -1,27 +1,25 @@ import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; -import NoSsr from '@material-ui/core/NoSsr'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; -const StyledButton = styled(Button)` - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +const SliderCustomized = styled(Slider)` + color: #20b2aa; - &:hover { - background-color: #5469d4; + :hover { + color: #2e8b57; } - & .MuiButton-label { - color: #fff; + & .MuiSlider-thumb { + border-radius: 1px; } `; export default function StyledComponentsDeep() { return ( - - - Customized - + + + + ); } diff --git a/docs/src/pages/guides/interoperability/StyledComponentsDeep.tsx b/docs/src/pages/guides/interoperability/StyledComponentsDeep.tsx index f5446e973b4b32..d1f0130d956856 100644 --- a/docs/src/pages/guides/interoperability/StyledComponentsDeep.tsx +++ b/docs/src/pages/guides/interoperability/StyledComponentsDeep.tsx @@ -1,27 +1,25 @@ import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; -import NoSsr from '@material-ui/core/NoSsr'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; -const StyledButton = styled(Button)` - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +const SliderCustomized = styled(Slider)` + color: #20b2aa; - &:hover { - background-color: #5469d4; + :hover { + color: #2e8b57; } - & .MuiButton-label { - color: #fff; + & .MuiSlider-thumb { + border-radius: 1px; } `; export default function StyledComponentsDeep() { return ( - - - Customized - + + + + ); } diff --git a/docs/src/pages/guides/interoperability/StyledComponentsTheme.js b/docs/src/pages/guides/interoperability/StyledComponentsTheme.js index 05bd366b31e79d..52021db7aebc59 100644 --- a/docs/src/pages/guides/interoperability/StyledComponentsTheme.js +++ b/docs/src/pages/guides/interoperability/StyledComponentsTheme.js @@ -1,47 +1,37 @@ import * as React from 'react'; -import styled, { ThemeProvider } from 'styled-components'; -import NoSsr from '@material-ui/core/NoSsr'; import { createMuiTheme, - ThemeProvider as MuiThemeProvider, + experimentalStyled as styled, + ThemeProvider, darken, } from '@material-ui/core/styles'; -import Button from '@material-ui/core/Button'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; const customTheme = createMuiTheme({ palette: { primary: { - main: '#6772e5', + main: '#20b2aa', }, }, }); -const StyledButton = styled(Button)` - ${({ theme }) => ` - background-color: ${theme.palette.primary.main}; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 4px 10px; - font-size: 13px; - &:hover { - background-color: ${darken(theme.palette.primary.main, 0.2)}; - } - ${theme.breakpoints.up('sm')} { - font-size: 14px; - padding: 7px 14px; +const CustomizedSlider = styled(Slider)( + ({ theme }) => ` + color: ${theme.palette.primary.main}; + + :hover { + color: ${darken(theme.palette.primary.main, 0.2)}; } - `} -`; +`, +); export default function StyledComponentsTheme() { return ( - - - - - Customized - - - + + + + + ); } diff --git a/docs/src/pages/guides/interoperability/StyledComponentsTheme.tsx b/docs/src/pages/guides/interoperability/StyledComponentsTheme.tsx index 05bd366b31e79d..52021db7aebc59 100644 --- a/docs/src/pages/guides/interoperability/StyledComponentsTheme.tsx +++ b/docs/src/pages/guides/interoperability/StyledComponentsTheme.tsx @@ -1,47 +1,37 @@ import * as React from 'react'; -import styled, { ThemeProvider } from 'styled-components'; -import NoSsr from '@material-ui/core/NoSsr'; import { createMuiTheme, - ThemeProvider as MuiThemeProvider, + experimentalStyled as styled, + ThemeProvider, darken, } from '@material-ui/core/styles'; -import Button from '@material-ui/core/Button'; +import Slider from '@material-ui/lab/SliderStyled'; +import Box from '@material-ui/core/Box'; const customTheme = createMuiTheme({ palette: { primary: { - main: '#6772e5', + main: '#20b2aa', }, }, }); -const StyledButton = styled(Button)` - ${({ theme }) => ` - background-color: ${theme.palette.primary.main}; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 4px 10px; - font-size: 13px; - &:hover { - background-color: ${darken(theme.palette.primary.main, 0.2)}; - } - ${theme.breakpoints.up('sm')} { - font-size: 14px; - padding: 7px 14px; +const CustomizedSlider = styled(Slider)( + ({ theme }) => ` + color: ${theme.palette.primary.main}; + + :hover { + color: ${darken(theme.palette.primary.main, 0.2)}; } - `} -`; +`, +); export default function StyledComponentsTheme() { return ( - - - - - Customized - - - + + + + + ); } diff --git a/docs/src/pages/guides/interoperability/interoperability.md b/docs/src/pages/guides/interoperability/interoperability.md index 5007f7a4516cb9..684f7b0ec3506d 100644 --- a/docs/src/pages/guides/interoperability/interoperability.md +++ b/docs/src/pages/guides/interoperability/interoperability.md @@ -1,6 +1,6 @@ # Style Library Interoperability -

While you can use the JSS based styling solution provided by Material-UI to style your application, you can also use the one you already know and love (from plain CSS to styled-components).

+

While you can use the emotion based styling solution provided by Material-UI to style your application, you can also use the one you already know and love (from plain CSS to styled-components).

This guide aims to document the most popular alternatives, but you should find that the principles applied here can be adapted to other libraries. @@ -18,96 +18,143 @@ Nothing fancy, just plain CSS. {{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}} -[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/plain-css-mtzri) +[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/plain-css-fdue7) -**PlainCssButton.css** +**PlainCssSlider.css** ```css -.button { - background-color: #6772e5; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +.slider { + color: #20b2aa; } -.button:hover { - background-color: #5469d4; + +.slider:hover { + color: #2e8b57; } ``` -**PlainCssButton.js** +**PlainCssSlider.js** ```jsx import * as React from 'react'; -import Button from '@material-ui/core/Button'; -import './PlainCssButton.css'; +import Slider from '@material-ui/lab/SliderStyled'; +import './PlainCssSlider.css'; -export default function PlainCssButton() { +export default function PlainCssSlider() { return (
- - + +
); } ``` -### Controlling priority ⚠️ +### CSS injection order ⚠️ -**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo: +**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion: ```jsx -import { StylesProvider } from '@material-ui/core/styles'; +import * as React from 'react'; +import { CacheProvider } from '@emotion/core'; +import createCache from '@emotion/cache'; + +const head = document.getElementsByTagName('head')[0]; + +const emotionContainer = head.insertBefore( + document.createElement('STYLE'), + head.firstChild, +); + +const cache = createCache({ + container: emotionContainer, +}); -{/* Your component tree. - Now, you can override Material-UI's styles. */}; +export default function PlainCssPriority() { + return ( + + {/* Your component tree. Now you can override Material-UI's styles. */} + + ); +} ``` ### Deeper elements -If you attempt to style a Drawer with variant permanent, -you will likely need to affect the Drawer's child paper element. -However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work. -You need to use the [`classes`](/styles/advanced/#overriding-styles-classes-prop) API of Material-UI. +If you attempt to style the Slider, +you will likely need to affect some of the Slider's child elements, for example the thumb. +In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same. -The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself. +The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself. -{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}} +{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}} + +**PlainCssSliderDeep1.css** + +```css +.slider { + color: #20b2aa; +} + +.slider:hover { + color: #2e8b57; +} + +.slider .MuiSlider-thumb { + border-radius: 1px; +} +``` -**PlainCssButtonDeep.css** +**PlainCssSliderDeep1.js** + +```jsx +import * as React from 'react'; +import Slider from '@material-ui/lab/SliderStyled'; +import './PlainCssSliderDeep1.css'; + +export default function PlainCssSliderDeep1() { + return ( +
+ + +
+ ); +} +``` + +The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API. + +**PlainCssSliderDeep2.css** ```css -.button { - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +.slider { + color: #20b2aa; } -.button:hover { - background-color: #5469d4; + +.slider:hover { + color: #2e8b57; } -.button-label { - color: #fff; + +.slider .thumb { + border-radius: 1px; } ``` -**PlainCssButtonDeep.js** +**PlainCssSliderDeep2.js** ```jsx import * as React from 'react'; -import Button from '@material-ui/core/Button'; -import './PlainCssButtonDeep.css'; +import Slider from '@material-ui/lab/SliderStyled'; +import './PlainCssSliderDeep2.css'; -export default function PlainCssButtonDeep() { +export default function PlainCssSliderDeep2() { return (
- - + +
); } @@ -118,45 +165,97 @@ export default function PlainCssButtonDeep() { Explicitly providing the class names to the component is too much effort? [You can target the class names generated by Material-UI](/styles/advanced/#with-material-ui-core). -[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/global-css-bir9e) +[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/global-classnames-dho8k) -**GlobalCssButton.css** +**GlobalCssSlider.css** ```css -.MuiButton-root { - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +.MuiSlider-root { + color: #20b2aa; } -.MuiButton-root:hover { - background-color: #5469d4; + +.MuiSlider-root:hover { + color: #2e8b57; } -.MuiButton-label { - color: #fff; +``` + +**GlobalCssSlider.js** + +```jsx +import * as React from 'react'; +import Slider from '@material-ui/lab/SliderStyled'; +import './GlobalCssSlider.css'; + +export default function GlobalCssSlider() { + return ; } ``` -**GlobalCssButton.js** +### CSS injection order ⚠️ + +**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion: ```jsx import * as React from 'react'; -import Button from '@material-ui/core/Button'; -import './GlobalCssButton.css'; +import { CacheProvider } from '@emotion/core'; +import createCache from '@emotion/cache'; + +const head = document.getElementsByTagName('head')[0]; -export default function GlobalCssButton() { - return ; +const emotionContainer = head.insertBefore( + document.createElement('STYLE'), + head.firstChild, +); + +const cache = createCache({ + container: emotionContainer, +}); + +export default function GlobalCssPriority() { + return ( + + {/* Your component tree. Now you can override Material-UI's styles. */} + + ); } ``` -### Controlling priority ⚠️ +### Deeper elements + +If you attempt to style the Slider, +you will likely need to affect some of the Slider's child elements, for example the thumb. +In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same. + +The following example overrides the slider's `thumb` style in addition to the custom styles on the slider itself. + +{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}} + +**GlobalCssSliderDeep.css** -**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo: +```css +.MuiSlider-root { + color: #20b2aa; +} + +.MuiSlider-root:hover { + color: #2e8b57; +} + +.MuiSlider-root .MuiSlider-thumb { + border-radius: 1px; +} +``` + +**GlobalCssSliderDeep.js** ```jsx -import { StylesProvider } from '@material-ui/core/styles'; +import * as React from 'react'; +import Slider from '@material-ui/lab/SliderStyled'; +import './GlobalCssSliderDeep.css'; -{/* Your component tree. - Now, you can override Material-UI's styles. */}; +export default function GlobalCssSliderDeep() { + return ; +} ``` ## Styled Components @@ -164,116 +263,100 @@ import { StylesProvider } from '@material-ui/core/styles'; ![stars](https://img.shields.io/github/stars/styled-components/styled-components.svg?style=social&label=Star) ![npm](https://img.shields.io/npm/dm/styled-components.svg?) -The `styled()` method works perfectly on all of the components. +### Change the default styled engine + +By default, Material-UI components come with emotion as their style engine. If, +however, you would like to use `styled-components`, you are can configure your app by following this [example project](https://github.com/mui-org/material-ui/blob/next/examples/create-react-app-with-styled-components). +Following this approach reduces the bundle size, and removes the need to configure the CSS injection order. + +After the style engine is configured properly, you can use the `experimentalStyled()` utility +from `@material-ui/core/styles` and have direct access to the theme. {{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}} -[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/styled-components-r1fsr) +[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/styled-components-interoperability-w9z9d) ```jsx import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; - -const StyledButton = styled(Button)` - background-color: #6772e5; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; - &:hover { - background-color: #5469d4; +import Slider from '@material-ui/lab/SliderStyled'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; + +const CustomizedSlider = styled(Slider)` + color: #20b2aa; + + :hover { + color: #2e8b57; } `; export default function StyledComponents() { - return ( -
- - Customized -
- ); + return ; } ``` -### Controlling priority ⚠️ - -**Note:** Both styled-components and JSS inject their styles at the bottom of the ``. -The best approach to ensuring styled-components styles are loaded last is to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo: - -```jsx -import { StylesProvider } from '@material-ui/core/styles'; - -{/* Your component tree. - Now, you can override Material-UI's styles. */}; -``` - -Another approach is to use the `&&` characters in styled-components to [bump up specificity](https://www.styled-components.com/docs/advanced#issues-with-specificity) by repeating the class name. Avoid the usage of `!important`. - ### Deeper elements -If you attempt to style a Drawer with variant permanent, -you will likely need to affect the Drawer's child paper element. -However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work. -You need to use the Material-UI [`classes`](/styles/advanced/#overriding-styles-classes-prop) API. +If you attempt to style the Slider, +you will likely need to affect some of the Slider's child elements, for example the thumb. +In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same. -The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself. -It also works around [this styled-components issue](https://github.com/styled-components/styled-components/issues/439) by "consuming" props that should not be passed on to the underlying component. +The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself. -{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js"}} +{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "defaultCodeOpen": false}} ```jsx import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; - -const StyledButton = styled(Button)` - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; - &:hover { - background-color: #5469d4; +import Slider from '@material-ui/lab/SliderStyled'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; + +const CustomizedSlider = styled(Slider)` + color: #20b2aa; + + :hover { + color: #2e8b57; } - & .MuiButton-label { - color: #fff; + + & .MuiSlider-thumb { + border-radius: 1px; } `; -export default function StyledComponentsDeep() { +export default function StyledComponentsDeep1() { return (
- - Customized + +
); } ``` -The above demo relies on the [default `classes` values](/styles/advanced/#with-material-ui-core) but you can provide your own class name: `.label`. +The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API. ```jsx import * as React from 'react'; -import styled from 'styled-components'; -import Button from '@material-ui/core/Button'; +import { experimentalStyled as styled } from '@material-ui/core/styles'; +import Slider from '@material-ui/lab/SliderStyled'; -const StyledButton = styled(({ color, ...other }) => ( - - Customized + + ); } @@ -281,61 +364,34 @@ export default function StyledComponentsDeep() { ### Theme -Material-UI has a rich theme structure that you can leverage for -the color manipulations, the transitions, the media queries, and more. +By using the Material-UI theme provider, the theme will be available in the theme context +of the styled engine too (emotion or styled-components, depending on your configuration). -We encourage to share the same theme object between Material-UI and your styles. +> ⚠️ If you are **already** using a custom theme with styled-components or emotion, +> it might not be compatible with Material-UI's theme specification. If it's not +> compatible, you need to render Material-UI's ThemeProvider first. This will +> ensure the theme structures are isolated. This is ideal for the progressive adoption +> of Material-UI's components in the codebase. + +You are encouraged to share the same theme object between Material-UI and the rest of your project. ```jsx -const StyledButton = styled(Button)` - ${({ theme }) => ` - background-color: ${theme.palette.primary.main}; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 4px 10px; - font-size: 13px; - &:hover { - background-color: ${darken(theme.palette.primary.main, 0.2)}; - } - ${theme.breakpoints.up('sm')} { - font-size: 14px; - padding: 7px 14px; +const CustomizedSlider = styled(Slider)( + ({ theme }) => ` + color: ${theme.palette.primary.main}; + + :hover { + color: ${darken(theme.palette.primary.main, 0.2)}; } - `} -`; +`, +); ``` {{"demo": "pages/guides/interoperability/StyledComponentsTheme.js"}} ### Portals -The [Portal](/components/portal/) provides a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. -Because of the way styled-components scopes its CSS, you may run into issues where styling is not applied. - -For example, if you attempt to style the [Menu](/components/menus/) of a [Select](/components/selects/) component using the `MenuProps` prop, -you will need to pass along the `className` prop to the element being rendered outside of it's DOM hierarchy. -The following example shows a workaround: - -```jsx -import * as React from 'react'; -import styled from 'styled-components'; -import Menu from '@material-ui/core/Menu'; -import MenuItem from '@material-ui/core/MenuItem'; - -const StyledMenu = styled(({ className, ...props }) => ( - -))` - box-shadow: none; - border: 1px solid #d3d4d5; - - li { - padding-top: 8px; - padding-bottom: 8px; - } -`; -``` - -{{"demo": "pages/guides/interoperability/StyledComponentsPortal.js"}} +TODO: fill this section after the portal is implemented with the new styled engine. ## CSS Modules @@ -346,91 +402,146 @@ bundling solution people are using. {{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}} -[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/css-modules-3j29h) +[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/css-modules-nuyg8) -**CssModulesButton.css** +**CssModulesSlider.module.css** ```css -.button { - background-color: #6772e5; - color: #fff; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +.slider { + color: #20b2aa; } -.button:hover { - background-color: #5469d4; + +.slider:hover { + color: #2e8b57; } ``` -**CssModulesButton.js** +**CssModulesSlider.js** ```jsx -import * as React from 'react'; +import React from 'react'; +import Slider from '@material-ui/lab/SliderStyled'; // webpack, parcel or else will inject the CSS into the page -import styles from './CssModulesButton.css'; -import Button from '@material-ui/core/Button'; +import styles from './CssModulesSlider.module.css'; -export default function CssModulesButton() { +export default function CssModulesSlider() { return (
- - + +
); } ``` -### Controlling priority ⚠️ +### CSS injection order ⚠️ -**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo: +**Note:** Most CSS-in-JS solutions inject their styles at the bottom of the HTML ``, which gives Material-UI precedence over your custom styles. To remove the need for **!important**, you need to change the CSS injection order. Here's a demo of how it can be done for the default style engine - emotion: ```jsx -import { StylesProvider } from '@material-ui/core/styles'; +import * as React from 'react'; +import { CacheProvider } from '@emotion/core'; +import createCache from '@emotion/cache'; -{/* Your component tree. - Now, you can override Material-UI's styles. */}; +const head = document.getElementsByTagName('head')[0]; + +const emotionContainer = head.insertBefore( + document.createElement('STYLE'), + head.firstChild, +); + +const cache = createCache({ + container: emotionContainer, +}); + +export default function CssModulesPriority() { + return ( + + {/* Your component tree. Now you can override Material-UI's styles. */} + + ); +} ``` ### Deeper elements -If you attempt to style a Drawer with variant permanent, -you will likely need to affect the Drawer's child paper element. -However, the paper is not the root element of Drawer and therefore styled-components customization as above will not work. -You need to use the [`classes`](/styles/advanced/#overriding-styles-classes-prop) API of Material-UI. +If you attempt to style the Slider, +you will likely need to affect some of the Slider's child elements, for example the thumb. +In Material-UI, all child elements have an increased specificity of 2: `.parent .child {}`. When writing overrides, you need to do the same. -The following example overrides the `label` style of `Button` in addition to the custom styles on the button itself. +The following examples override the slider's `thumb` style in addition to the custom styles on the slider itself. -{{"demo": "pages/guides/interoperability/StyledComponents.js", "hideToolbar": true}} +{{"demo": "pages/guides/interoperability/StyledComponentsDeep.js", "hideToolbar": true}} -**CssModulesButtonDeep.css** +**CssModulesSliderDeep1.module.css** ```css -.root { - background-color: #6772e5; - box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); - padding: 7px 14px; +.slider { + color: #20b2aa; } -.root:hover { - background-color: #5469d4; + +.slider:hover { + color: #2e8b57; } -.label { - color: #fff; + +.slider .MuiSlider-thumb { + border-radius: 1px; } ``` -**CssModulesButtonDeep.js** +**CssModulesSliderDeep1.js** ```jsx -import * as React from 'react'; +import React from 'react'; // webpack, parcel or else will inject the CSS into the page -import styles from './CssModulesButtonDeep.css'; -import Button from '@material-ui/core/Button'; +import styles from './CssModulesSliderDeep1.module.css'; +import Slider from '@material-ui/lab/SliderStyled'; -export default function CssModulesButtonDeep() { +export default function CssModulesSliderDeep1() { return (
- - + + +
+ ); +} +``` + +The above demo relies on the [default `className` values](/styles/advanced/#with-material-ui-core), but you can provide your own class name with the `componentsProps` API. + +**CssModulesSliderDeep2.module.css** + +```css +.slider { + color: #20b2aa; +} + +.slider:hover { + color: #2e8b57; +} + +.slider .thumb { + border-radius: 1px; +} +``` + +**CssModulesSliderDeep2.js** + +```jsx +import React from 'react'; +// webpack, parcel or else will inject the CSS into the page +import styles from './CssModulesSliderDeep2.module.css'; +import Slider from '@material-ui/lab/SliderStyled'; + +export default function CssModulesSliderDeep2() { + return ( +
+ +
); } @@ -447,75 +558,35 @@ Emotion's **css()** method works seamlessly with Material-UI. {{"demo": "pages/guides/interoperability/EmotionCSS.js", "hideToolbar": true}} -[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/emotion-bgfxj) +[![Edit Button](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/emotion-interoperability-idymy) ```jsx /** @jsx jsx */ import { jsx, css } from '@emotion/core'; -import Button from '@material-ui/core/Button'; +import Slider from '@material-ui/lab/SliderStyled'; export default function EmotionCSS() { return (
- - + />
); } ``` -### Controlling priority ⚠️ - -**Note:** JSS injects its styles at the bottom of the ``. If you don't want to mark style attributes with **!important**, you need to change [the CSS injection order](/styles/advanced/#css-injection-order), as in the demo: - -```jsx -import { StylesProvider } from '@material-ui/core/styles'; - -{/* Your component tree. - Now, you can override Material-UI's styles. */}; -``` - ### Theme -Material-UI has a rich theme structure that you can leverage for -the color manipulations, the transitions, the media queries, and more. - -We encourage to share the same theme object between Material-UI and your styles. - -```jsx - -``` - -{{"demo": "pages/guides/interoperability/EmotionTheme.js"}} +It works exactly like styled components. You can [use the same guide](/guides/interoperability/#styled-components). ### The `styled()` API