-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[system] Fix color-scheme implementation (#34639)
- Loading branch information
1 parent
daed91d
commit 0c4b1f5
Showing
32 changed files
with
710 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
--- | ||
product: joy-ui | ||
githubLabel: 'component: CssBaseline' | ||
--- | ||
|
||
# CSS Baseline | ||
|
||
<p class="description">Joy UI provides a CssBaseline component to kickstart an elegant, consistent, and simple baseline to build upon.</p> | ||
|
||
{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} | ||
|
||
## Global reset | ||
|
||
You might be familiar with [normalize.css](https://github.com/necolas/normalize.css), a collection of HTML element and attribute style-normalizations. | ||
|
||
```jsx | ||
import * as React from 'react'; | ||
import { CssVarsProvider } from '@mui/joy/styles'; | ||
import CssBaseline from '@mui/joy/CssBaseline'; | ||
|
||
export default function MyApp() { | ||
return ( | ||
<CssVarsProvider> | ||
{/* must be used under CssVarsProvider */} | ||
<CssBaseline /> | ||
|
||
{/* The rest of your application */} | ||
</CssVarsProvider> | ||
); | ||
} | ||
``` | ||
|
||
## Scoping on children | ||
|
||
However, you might be progressively migrating a website to MUI, using a global reset might not be an option. | ||
It's possible to apply the baseline only to the children by using the `ScopedCssBaseline` component. | ||
|
||
```jsx | ||
import * as React from 'react'; | ||
import { CssVarsProvider } from '@mui/joy/styles'; | ||
import ScopedCssBaseline from '@mui/joy/ScopedCssBaseline'; | ||
import MyApp from './MyApp'; | ||
|
||
export default function MyApp() { | ||
const [root, setRoot] = React.useState(null); | ||
return ( | ||
{/* target the node to ScopedCssBaseline's div */} | ||
<CssVarsProvider colorSchemeNode={root}> | ||
{/* must be used under CssVarsProvider */} | ||
<ScopedCssBaseline ref={(element) => setRoot(element)}> | ||
{/* The rest of your application */} | ||
<MyApp /> | ||
</ScopedCssBaseline> | ||
</CssVarsProvider> | ||
); | ||
} | ||
``` | ||
|
||
⚠️ Make sure you import `ScopedCssBaseline` first to avoid box-sizing conflicts as in the above example. | ||
|
||
## Approach | ||
|
||
### Page | ||
|
||
The `<html>` and `<body>` elements are updated to provide better page-wide defaults. More specifically: | ||
|
||
- The margin in all browsers is removed. | ||
- The default Material Design background color is applied. | ||
It's using `theme.palette.background.body` for standard devices and a white background for print devices. | ||
- The CSS [`color-scheme`](https://web.dev/color-scheme/) is applied by default. You can disable it by setting `disableColorScheme` to true on the `CssBaseline` or `ScopedCssBaseline`. | ||
|
||
### Layout | ||
|
||
- `box-sizing` is set globally on the `<html>` element to `border-box`. | ||
Every element—including `*::before` and `*::after` are declared to inherit this property, which ensures that the declared width of the element is never exceeded due to padding or border. | ||
|
||
### Color scheme | ||
|
||
The CSS [`color-scheme`](https://web.dev/color-scheme/) is applied by default to render proper built-in components on the web. You can disable it by setting `disableColorScheme` to true on the `CssBaseline` or `ScopedCssBaseline`. | ||
|
||
```jsx | ||
<CssVarsProvider> | ||
<CssBaseline disableColorScheme /> | ||
</CssVarsProvider> | ||
|
||
// or | ||
<CssVarsProvider> | ||
<ScopedCssBaseline disableColorScheme > | ||
{/* The rest of your application */} | ||
</ScopedCssBaseline> | ||
</CssVarsProvider> | ||
``` | ||
|
||
### Typography | ||
|
||
- No base font-size is declared on the `<html>`, but 16px is assumed (the browser default). | ||
You can learn more about the implications of changing the `<html>` default font size in [the theme documentation](/material-ui/customization/typography/#html-font-size) page. | ||
- Set the `theme.typography.body1` style on the `<body>` element. | ||
- Set the font-weight to `bold` for the `<b>` and `<strong>` elements. | ||
- Custom font-smoothing is enabled for better display of the default font. | ||
|
||
## Customization | ||
|
||
### CssBaseline | ||
|
||
To custom the styles produced by the `CssBaseline` component, append the `GlobalStyles` next to it: | ||
|
||
```js | ||
import { CssVarsProvider } from '@mui/joy/styles'; | ||
import CssBaseline from '@mui/joy/CssBaseline'; | ||
import GlobalStyles from '@mui/joy/GlobalStyles'; | ||
|
||
function App() { | ||
return ( | ||
<CssVarsProvider> | ||
<CssBaseline /> {/* CssBaseline must come first */} | ||
<GlobalStyles | ||
styles={{ | ||
// CSS object styles | ||
html: { | ||
// ... | ||
}, | ||
body: { | ||
// ... | ||
}, | ||
}} | ||
/> | ||
</CssVarsProvider> | ||
); | ||
} | ||
``` | ||
|
||
### ScopedCssBaseline | ||
|
||
You can customize it using the [themed components](https://mui.com/joy-ui/customization/themed-components/) approach. The component identifier is `JoyScopedCssBaseline` which contains only the `root` slot. | ||
|
||
```js | ||
import { CssVarsProvider, extendTheme } from '@mui/joy/styles'; | ||
import ScopedCssBaseline from '@mui/joy/ScopedCssBaseline'; | ||
import MyApp from './MyApp'; | ||
|
||
const theme = extendTheme({ | ||
components: { | ||
JoyScopedCssBaseline: { | ||
styleOverrides: { | ||
root: ({ theme }) => ({ | ||
// ...CSS object styles | ||
}) | ||
} | ||
} | ||
} | ||
}) | ||
|
||
export default function MyApp() { | ||
const [root, setRoot] = React.useState(null); | ||
return ( | ||
{/* target the node to ScopedCssBaseline's div */} | ||
<CssVarsProvider colorSchemeNode={root}> | ||
{/* must be used under CssVarsProvider */} | ||
<ScopedCssBaseline ref={(element) => setRoot(element)}> | ||
{/* The rest of your application */} | ||
<MyApp /> | ||
</ScopedCssBaseline> | ||
</CssVarsProvider> | ||
); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as React from 'react'; | ||
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; | ||
import * as pageProps from 'docs/data/joy/components/css-baseline/css-baseline.md?@mui/markdown'; | ||
|
||
export default function Page() { | ||
return <MarkdownDocs {...pageProps} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import * as React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { GlobalStyles } from '@mui/system'; | ||
import { Theme, DefaultColorScheme, ColorSystem } from '../styles/types'; | ||
import { CssBaselineProps } from './CssBaselineProps'; | ||
|
||
/** | ||
* Kickstart an elegant, consistent, and simple baseline to build upon. | ||
*/ | ||
function CssBaseline({ children, disableColorScheme = false }: CssBaselineProps) { | ||
return ( | ||
<React.Fragment> | ||
<GlobalStyles | ||
styles={(theme: Theme) => { | ||
const colorSchemeStyles: Record<string, any> = {}; | ||
if (!disableColorScheme) { | ||
// The CssBaseline is wrapped inside a CssVarsProvider | ||
( | ||
Object.entries(theme.colorSchemes) as Array<[DefaultColorScheme, ColorSystem]> | ||
).forEach(([key, scheme]) => { | ||
colorSchemeStyles[theme.getColorSchemeSelector(key).replace(/\s*&/, '')] = { | ||
colorScheme: scheme.palette?.mode, | ||
}; | ||
}); | ||
} | ||
return { | ||
html: { | ||
WebkitFontSmoothing: 'antialiased', | ||
MozOsxFontSmoothing: 'grayscale', | ||
// Change from `box-sizing: content-box` so that `width` | ||
// is not affected by `padding` or `border`. | ||
boxSizing: 'border-box', | ||
// Fix font resize problem in iOS | ||
WebkitTextSizeAdjust: '100%', | ||
}, | ||
'*, *::before, *::after': { | ||
boxSizing: 'inherit', | ||
}, | ||
'strong, b': { | ||
fontWeight: 'bold', | ||
}, | ||
body: { | ||
margin: 0, // Remove the margin in all browsers. | ||
color: theme.vars.palette.text.primary, | ||
...(theme.typography.body1 as any), | ||
backgroundColor: theme.vars.palette.background.body, | ||
'@media print': { | ||
// Save printer ink. | ||
backgroundColor: theme.vars.palette.common.white, | ||
}, | ||
// Add support for document.body.requestFullScreen(). | ||
// Other elements, if background transparent, are not supported. | ||
'&::backdrop': { | ||
backgroundColor: theme.vars.palette.background.backdrop, | ||
}, | ||
}, | ||
...colorSchemeStyles, | ||
}; | ||
}} | ||
/> | ||
{children} | ||
</React.Fragment> | ||
); | ||
} | ||
|
||
CssBaseline.propTypes /* remove-proptypes */ = { | ||
// ----------------------------- Warning -------------------------------- | ||
// | These PropTypes are generated from the TypeScript type definitions | | ||
// | To update them edit TypeScript types and run "yarn proptypes" | | ||
// ---------------------------------------------------------------------- | ||
/** | ||
* You can wrap a node. | ||
*/ | ||
children: PropTypes.node, | ||
/** | ||
* Disable `color-scheme` CSS property. | ||
* | ||
* For more details, check out https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme | ||
* For browser support, check out https://caniuse.com/?search=color-scheme | ||
* @default false | ||
*/ | ||
disableColorScheme: PropTypes.bool, | ||
} as any; | ||
|
||
export default CssBaseline; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export interface CssBaselineProps { | ||
/** | ||
* You can wrap a node. | ||
*/ | ||
children?: React.ReactNode; | ||
/** | ||
* Disable `color-scheme` CSS property. | ||
* | ||
* For more details, check out https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme | ||
* For browser support, check out https://caniuse.com/?search=color-scheme | ||
* @default false | ||
*/ | ||
disableColorScheme?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default } from './CssBaseline'; | ||
export * from './CssBaselineProps'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { GlobalStyles as default } from '@mui/system'; |
20 changes: 20 additions & 0 deletions
20
packages/mui-joy/src/ScopedCssBaseline/ScopedCssBaseline.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import * as React from 'react'; | ||
import { createRenderer, describeConformance } from 'test/utils'; | ||
import { ThemeProvider } from '@mui/joy/styles'; | ||
import ScopedCssBaseline, { scopedCssBaselineClasses as classes } from '@mui/joy/ScopedCssBaseline'; | ||
|
||
describe('<ScopedCssBaseline />', () => { | ||
const { render } = createRenderer(); | ||
|
||
describeConformance(<ScopedCssBaseline />, () => ({ | ||
classes, | ||
inheritComponent: 'div', | ||
render, | ||
ThemeProvider, | ||
muiName: 'JoyScopedCssBaseline', | ||
refInstanceof: window.HTMLDivElement, | ||
testComponentPropWith: 'span', | ||
testVariantProps: { disableColorScheme: true }, | ||
skip: ['classesRoot', 'componentsProp'], | ||
})); | ||
}); |
Oops, something went wrong.