Pular para o conteúdo

Shadow DOM

O shadow DOM permite que você encapsule partes de uma aplicação para manter elas separadas do estilo global que visam a árvore DOM regular.

Como se usar o shadow DOM com Material UI

1. Estilos

O shadow DOM é uma api que fornece uma forma de anexar um DOM oculto separado a um elemento Isso é útil quando você precisa manter a estrutura, estilos e comportamentos de componentes diferentes separados do resto do código na página, para evitar conflitos. Veja a a documentação do MDN na documentação do shadow DOM para mais informações. O seguinte código mostra como se aplicar estilos em um shadow DOM:

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. Tema

Os componentes MUI como Menu, Dialog, Popover e outros usam o Portal para renderizar uma nova "sub árvore" em um container fora da atual hierarquia do DOM. Por padrão, esse container é document.body. Mas dado que os estilos são apenas aplicados dentro do Shadow DOM, nós também precisamos renderizar os portais dentro do conteiner do Shadow DOM.

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

// ...

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

Demostração

No exemplo abaixo é possível ver que o componente fora do shadow DOM é afetado pelos estilos globais, enquanto o componente dentro do shadow DOM não é: