Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] Add Shadow DOM guide #33007

Merged
merged 3 commits into from
Jun 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/data/material/guides/shadow-dom/ShadowDOMDemo.js
@@ -0,0 +1,16 @@
import * as React from 'react';

export default function ShadowDOMDemo() {
return (
<iframe
title="codesandbox"
src="https://codesandbox.io/embed/basicselect-demo-material-ui-forked-rki9k5?hidenavigation=1&fontsize=14&view=preview&hidedevtools=1"
style={{
width: '100%',
height: 350,
border: 0,
}}
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin hidenavigation"
/>
);
}
16 changes: 16 additions & 0 deletions docs/data/material/guides/shadow-dom/ShadowDOMDemo.tsx
@@ -0,0 +1,16 @@
import * as React from 'react';

export default function ShadowDOMDemo() {
return (
<iframe
title="codesandbox"
src="https://codesandbox.io/embed/basicselect-demo-material-ui-forked-rki9k5?hidenavigation=1&fontsize=14&view=preview&hidedevtools=1"
style={{
width: '100%',
height: 350,
border: 0,
}}
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin hidenavigation"
/>
);
}
10 changes: 10 additions & 0 deletions docs/data/material/guides/shadow-dom/ShadowDOMDemo.tsx.preview
@@ -0,0 +1,10 @@
<iframe
title="codesandbox"
src="https://codesandbox.io/embed/basicselect-demo-material-ui-forked-rki9k5?hidenavigation=1&fontsize=14&view=preview&hidedevtools=1"
style={{
width: '100%',
height: 350,
border: 0,
}}
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin hidenavigation"
/>
64 changes: 64 additions & 0 deletions docs/data/material/guides/shadow-dom/shadow-dom.md
@@ -0,0 +1,64 @@
# Shadow DOM

<p class="description"><a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM" target="_blank" rel="noopener nofollow">Shadow DOM</a> can be helpful to isolate part of the app from unwanted global styles.</p>
cherniavskii marked this conversation as resolved.
Show resolved Hide resolved

## Steps
cherniavskii marked this conversation as resolved.
Show resolved Hide resolved

### 1. Styles

In order for styles to work in Shadow DOM, they need to be applied inside of the Shadow DOM:
cherniavskii marked this conversation as resolved.
Show resolved Hide resolved

```tsx
const container = document.querySelector('#root');
const shadowContainer = container.attachShadow({ mode: 'open' });
const emotionRoot = document.createElement('style');
const shadowRootElement = document.createElement('div');
shadowContainer.appendChild(emotionRoot);
shadowContainer.appendChild(shadowRootElement);

const cache = createCache({
key: 'css',
prepend: true,
container: emotionRoot,
});

ReactDOM.createRoot(shadowRootElement).render(
<CacheProvider value={cache}>
<App />
</CacheProvider>,
);
```

### 2. Theme

MUI components like `Menu`, `Dialog`, `Popover` and others use [React Portal](https://reactjs.org/docs/portals.html) to render a new "subtree" in a container outside of current DOM hierarchy.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing MUI with Material UI to be more specific.

Should we replace this Portal link with our own Portal docs? (If so, we still need to update the Material UI portal docs to match the Base portal docs.)

Suggested change
MUI components like `Menu`, `Dialog`, `Popover` and others use [React Portal](https://reactjs.org/docs/portals.html) to render a new "subtree" in a container outside of current DOM hierarchy.
Material UI components like `Menu`, `Dialog`, `Popover` and others use [React Portal](https://reactjs.org/docs/portals.html) to render a new "subtree" in a container outside of current DOM hierarchy.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing MUI with Material UI to be more specific.

I would keep MUI, since it's relevant for MUI X and probably for Joy (in the future)

Should we replace this Portal link with our own Portal docs?

Sure 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep MUI, since it's relevant for MUI X and probably for Joy (in the future)

More and more I'm getting hints for an MUI-company-wide documentation 👁️ 👀 🙄
(stuff that isn't particular to one or two products but rather a company-wide philosophy/convention/approach)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I didn't even realise that this guide will be only available in Material UI docs.
I think a lot of pages from "How To Guides" menu section could make sense in other MUI Core products, and sometimes in MUI X as well.
We'll definitely need top-level docs at some point.

By default, this container is `document.body`. But since the styles are applied only inside of the Shadow DOM, we need to render portals inside the Shadow DOM container as well:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
By default, this container is `document.body`. But since the styles are applied only inside of the Shadow DOM, we need to render portals inside the Shadow DOM container as well:
By default, this container is `document.body`.
But since the styles are applied only inside of the shadow DOM, we need to render portals inside the shadow DOM container as well:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline doesn't make a difference in markdown.
Did you mean to split it into two paragraphs? An additional empty line is needed then

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to see each sentence on a new line to make it simpler to comment on individual sentences (rather than paragraphs). Sorry I should have explained that! It's a pattern that I think I saw @oliviertassinari enforce when I started contributing to the docs. Might be worth adding as a prettier rule if it's something we really want to standardize.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so you meant just a line break in markdown, right?


```tsx
const theme = createTheme({
components: {
MuiPopover: {
defaultProps: {
container: shadowRootElement,
},
},
MuiPopper: {
defaultProps: {
container: shadowRootElement,
},
},
},
});

// ...

<ThemeProvider theme={theme}>
<App />
</ThemeProvider>;
```

## Demo

In the example below you can see that component outside of the Shadow DOM is affected by global styles, while component inside of the Shadow DOM is not.
cherniavskii marked this conversation as resolved.
Show resolved Hide resolved

{{"demo": "ShadowDOMDemo.js", "defaultCodeOpen": false}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a few changes around this demo in #33122

1 change: 1 addition & 0 deletions docs/data/material/pages.ts
Expand Up @@ -208,6 +208,7 @@ const pages = [
{ pathname: '/material-ui/guides/content-security-policy', title: 'Content Security Policy' },
{ pathname: '/material-ui/guides/right-to-left', title: 'Right-to-left' },
{ pathname: '/material-ui/guides/flow' },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we could drop this page, it's outdated now. I have taken note in https://www.notion.so/mui-org/Opportunities-408a9771556a4715830d18f3749af753#167b4a8cef8e44e2a31c9c2568ec12fb.

{ pathname: '/material-ui/guides/shadow-dom', title: 'Shadow DOM' },
],
},
{
Expand Down
11 changes: 11 additions & 0 deletions docs/pages/material-ui/guides/shadow-dom.js
@@ -0,0 +1,11 @@
import * as React from 'react';
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
import {
demos,
docs,
demoComponents,
} from 'docs/data/material/guides/shadow-dom/shadow-dom.md?@mui/markdown';

export default function Page() {
return <MarkdownDocs demos={demos} docs={docs} demoComponents={demoComponents} />;
}
1 change: 1 addition & 0 deletions docs/translations/translations.json
Expand Up @@ -324,6 +324,7 @@
"/material-ui/guides/content-security-policy": "Content Security Policy",
"/material-ui/guides/right-to-left": "Right-to-left",
"/material-ui/guides/flow": "Flow",
"/material-ui/guides/shadow-dom": "Shadow DOM",
"/material-ui/experimental-api": "Experimental APIs",
"/material-ui/experimental-api/classname-generator": "ClassName generator",
"/material-ui/experimental-api/css-variables": "CSS variables",
Expand Down