Pular para o conteúdo

Modal

O componente modal fornece uma base sólida para criar diálogos, popovers, lightboxes ou qualquer outra coisa.

O componente renderiza o conteúdo de seu children sobre um componente backdrop. O Modal oferece recursos importantes:

  • 💄 Gerencia o empilhamento de chamadas quando ter um de cada vez não for suficiente.
  • 🔐 Cria um plano de fundo para desabilitar a interação abaixo do modal.
  • 🔐 Desativa a rolagem do conteúdo da página enquanto estiver aberto.
  • ♿️ Gerencia adequadamente o foco; movendo para o conteúdo modal, e mantendo-o lá até que o modal seja fechado.
  • ♿️ Adiciona as funções ARIA apropriadas automaticamente.

A paleta com funções de estilo.

Nota sobre a terminologia. O termo "modal" algumas vezes é usado com o sentido de "diálogo", mas isto é um equívoco. Uma janela modal descreve partes de uma UI. Um elemento é considerado modal se ele bloqueia interações com o resto da aplicação.

Se você está criando um diálogo modal, você provavelmente quer usar o componente Dialog em vez de diretamente um Modal. Modal é uma estrutura de baixo-nível que é aproveitada pelos seguintes componentes:

Basic modal

<Button onClick={handleOpen}>Open modal</Button>
<Modal
  open={open}
  onClose={handleClose}
  aria-labelledby="modal-modal-title"
  aria-describedby="modal-modal-description"
>
  <Box sx={style}>
    <Typography id="modal-modal-title" variant="h6" component="h2">
      Text in a modal
    </Typography>
    <Typography id="modal-modal-description" sx={{ mt: 2 }}>
      Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
    </Typography>
  </Box>
</Modal>

Você pode desativar o contorno (muitas vezes azul ou ouro) com a propriedade CSS outline: 0.

Unstyled

The modal also comes with an unstyled version. It's ideal for doing heavy customizations and minimizing bundle size.

import ModalUnstyled from '@material-ui/unstyled/ModalUnstyled';
<button type="button" onClick={handleOpen}>
  Open modal
</button>
<StyledModal
  aria-labelledby="unstyled-modal-title"
  aria-describedby="unstyled-modal-description"
  open={open}
  onClose={handleClose}
  BackdropComponent={Backdrop}
>
  <Box sx={style}>
    <h2 id="unstyled-modal-title">Text in a modal</h2>
    <p id="unstyled-modal-description">Aliquid amet deserunt earum!</p>
  </Box>
</StyledModal>

Nested modal

Modals can be nested, for example a select within a dialog, but stacking of more than two modals, or any two modals with a backdrop is discouraged.

<Button onClick={handleOpen}>Open modal</Button>
<Modal
  open={open}
  onClose={handleClose}
  aria-labelledby="parent-modal-title"
  aria-describedby="parent-modal-description"
>
  <Box sx={{ ...style, width: 400 }}>
    <h2 id="parent-modal-title">Text in a modal</h2>
    <p id="parent-modal-description">
      Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
    </p>
    <ChildModal />
  </Box>
</Modal>

Transições

O estado de aberto/fechado do modal pode ser animado com um componente de transição. Este componente deve respeitar as seguintes condições:

  • Seja um filho direto descendente do modal.
  • Tenha uma propriedade in. Isso corresponde ao estado de aberto/fechado.
  • Chamar a propriedade de callback onEnter quando a transição de entrada iniciar.
  • Chamar a propriedade de callback onExited quando a transição de saída for concluída. Esses dois callbacks permitem que o modal desmonte o conteúdo filho quando fechado e seja totalmente transitado.

O modal possui suporte interno para react-transition-group.

Como alternativa, você pode usar react-spring.

Performance

O conteúdo do modal é desmontado quando fechado. Se você precisa disponibilizar o conteúdo para mecanismos de busca ou renderizar árvores de componentes grandes dentro do seu modal enquanto otimiza interação responsiva, pode ser uma boa ideia mudar este comportamento padrão ativando a propriedade keepMounted:

<Modal keepMounted />

As with any performance optimization, this is not a silver bullet. Be sure to identify bottlenecks first, and then try out these optimization strategies.

Modal do lado do servidor

React não suporta a API createPortal() no servidor. Para exibir o modal, você precisa desativar o recurso portal com a propriedade disablePortal:

Limitações

Captura do foco

O modal move o foco de volta para o corpo do componente se o foco tentar escapar dele.

This is done for accessibility purposes. However, it might create issues. No caso de os usuários precisarem interagir com outra parte da página, por exemplo, com uma janela de chatbot, você pode desabilitar o comportamento:

<Modal disableEnforceFocus />

Acessibilidade

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#dialog_modal)

  • Certifique-se de adicionar aria-labelledby="id...", referenciando o título modal, ao Modal. Adicionalmente, você pode dar uma descrição do seu modal com a propriedade aria-describedby = "id..." no Modal.

    <Modal
      aria-labelledby="modal-title"
      aria-describedby="modal-description"
      >
      <h2 id="modal-title">
        Meu Título
      </h2>
      <p id="modal-description">
        Minha Descrição
      </p>
      </Modal>
    
  • O WAI-ARIA authoring practices pode ajudá-lo a definir o foco inicial no elemento mais relevante, com base no seu conteúdo modal.

  • Esteja ciente que uma "janela modal" sobrepõe a janela primária ou qualquer outra janela modal. Esteja ciente que uma "janela modal" sobrepõe a janela primária ou qualquer outra janela modal. Ou seja, os usuários não podem interagir com o conteúdo fora de uma janela modal ativa. Isso pode criar comportamentos conflitantes.