Skip to main content

Modal

O componente Modal é uma janela sobreposta que aparece sobre o conteúdo principal da aplicação. É ideal para exibir conteúdo importante que requer atenção imediata do usuário, como confirmações, formulários, ou informações detalhadas sem sair do contexto atual.

Importação

import { Modal } from '@useblu/ocean-react';

Importação específica (recomendado para tree-shaking)

import { Modal } from '@useblu/ocean-react/Modal';

Importação de tipos TypeScript

import type { ModalProps } from '@useblu/ocean-react';

// Uso em componente customizado
const MyModal: React.FC<{ isVisible: boolean }> = ({ isVisible }) => {
const [open, setOpen] = React.useState(isVisible);

return (
<Modal
isOpen={open}
onRequestClose={() => setOpen(false)}
contentLabel="Meu Modal"
maxWidth="md"
>
<div>Conteúdo do modal</div>
</Modal>
);
};

Playground Interativo

Explore o componente Modal no playground interativo do Storybook:

Documentação Completa

Para documentação técnica detalhada, exemplos de uso e API completa, consulte o Storybook do Modal.

No Storybook você encontrará:

  • Controles interativos para testar todas as props
  • API gerada automaticamente com tipagem completa
  • Exemplos visuais de todas as variantes e estados
  • Playground para experimentação rápida

Uso básico

function BasicModal() {
const [open, setOpen] = React.useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Abrir Modal</button>
<Modal
isOpen={open}
onRequestClose={() => setOpen(false)}
contentLabel="Modal básico"
>
<div>
<h2>Título do Modal</h2>
<p>Conteúdo do modal aqui.</p>
<button onClick={() => setOpen(false)}>Fechar</button>
</div>
</Modal>
</>
);
}

Tamanhos

O Modal oferece quatro tamanhos predefinidos para adequar-se ao conteúdo:

TamanhoLarguraUso recomendado
sm420pxConfirmações simples e alertas
md540pxFormulários e conteúdo geral (padrão)
lg660pxConteúdo extenso e formulários complexos
xl780pxConteúdo muito extenso e tabelas

Modal que se estende até a largura máxima disponível:

Para casos onde você quer controlar o fechamento apenas por ações específicas:

Responsividade

O Modal é automaticamente responsivo e se adapta a diferentes tamanhos de tela:

  • Desktop: Aparece centralizado com bordas arredondadas
  • Mobile: Aparece como bottom sheet com bordas arredondadas apenas no topo
  • Altura máxima: 80% da tela em dispositivos móveis
  • Transições: Animações suaves de abertura e fechamento

API

Props

PropTipoPadrãoDescrição
childrenReactNode-Conteúdo a ser exibido dentro do modal
isOpenboolean-Controla se o modal está aberto
onRequestClose(event: MouseEvent | KeyboardEvent) => void-Função chamada quando o modal é solicitado para fechar
blockedbooleanfalseSe true, o modal se estende até a largura máxima
maxWidth'sm' | 'md' | 'lg' | 'xl' | falsefalseDetermina a largura máxima do modal
disableClosebooleanfalseDesabilita o botão de fechar
contentLabelstring-Label para acessibilidade do conteúdo do modal
ariaHideAppbooleantrueControla se deve esconder a aplicação do screen reader
closeTimeoutMSnumber150Tempo de animação para fechar o modal em milissegundos

Eventos

  • onRequestClose: Disparado quando o usuário tenta fechar o modal (Escape, clique no overlay, botão fechar)

Classes CSS

O componente utiliza as seguintes classes CSS que podem ser customizadas:

ClasseDescrição
.ods-modalContainer portal do modal
.ods-modal__overlayOverlay de fundo do modal
.ods-modal__overlay--after-openModificador para overlay após abertura
.ods-modal__overlay--before-closeModificador para overlay antes do fechamento
.ods-modal__contentContainer principal do conteúdo do modal
.ods-modal__content--after-openModificador para conteúdo após abertura
.ods-modal__content--before-closeModificador para conteúdo antes do fechamento
.ods-modal__content--smModificador para modal de tamanho pequeno
.ods-modal__content--mdModificador para modal de tamanho médio
.ods-modal__content--lgModificador para modal de tamanho grande
.ods-modal__content--xlModificador para modal de tamanho extra grande
.ods-modal__content--blockedModificador para modal bloqueado
.ods-modal__headerCabeçalho do modal
.ods-modal__header-closeBotão de fechar do modal
.ods-modal__bodyCorpo do modal onde fica o conteúdo

Acessibilidade

  • ✅ Suporte completo a navegação por teclado
  • ✅ Foco automático no modal quando aberto
  • ✅ Escape para fechar o modal
  • ✅ Overlay clicável para fechar
  • ✅ Atributos ARIA apropriados
  • ✅ Gestão de foco para screen readers
  • ✅ Suporte ao contentLabel para identificação
TeclaFunção
EscapeFecha o modal
TabNavega pelos elementos

Melhores práticas

✅ Faça

  • Use para conteúdo importante que precisa de atenção imediata
  • Implemente fechamento via Escape e overlay
  • Forneça um contentLabel descritivo
  • Use tamanho apropriado para o conteúdo
  • Mantenha o foco dentro do modal quando aberto

❌ Não faça

  • Não use para navegação principal
  • Não omita formas de fechar o modal
  • Não coloque múltiplos modais abertos simultaneamente
  • Não use modal muito pequeno para conteúdo extenso
  • Não esqueça de gerenciar o foco adequadamente

Casos de uso comuns

function ConfirmationModal() {
const [open, setOpen] = React.useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Deletar Item</button>
<Modal
isOpen={open}
onRequestClose={() => setOpen(false)}
contentLabel="Confirmar exclusão"
maxWidth="sm"
>
<div style={{ padding: '24px', textAlign: 'center' }}>
<h2>Confirmar Exclusão</h2>
<p>
Tem certeza que deseja deletar este item? Esta ação não pode ser
desfeita.
</p>
<div
style={{ display: 'flex', gap: '12px', justifyContent: 'center' }}
>
<button onClick={() => setOpen(false)}>Cancelar</button>
<button
onClick={() => setOpen(false)}
style={{ background: 'red', color: 'white' }}
>
Deletar
</button>
</div>
</div>
</Modal>
</>
);
}
function FormModal() {
const [open, setOpen] = React.useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Novo Produto</button>
<Modal
isOpen={open}
onRequestClose={() => setOpen(false)}
contentLabel="Criar produto"
maxWidth="md"
>
<div style={{ padding: '24px' }}>
<h2>Novo Produto</h2>
<form>
<div>
<label>Nome do produto</label>
<input type="text" />
</div>
<div>
<label>Descrição</label>
</div>
<div>
<label>Preço</label>
<input type="number" />
</div>
<div>
<button type="button" onClick={() => setOpen(false)}>
Cancelar
</button>
<button type="submit">Salvar</button>
</div>
</form>
</div>
</Modal>
</>
);
}
function DetailsModal({ item }) {
const [open, setOpen] = React.useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Ver Detalhes</button>
<Modal
isOpen={open}
onRequestClose={() => setOpen(false)}
contentLabel="Detalhes do item"
maxWidth="lg"
>
<div>
<h2>{item.name}</h2>
<div>
<div>
<h3>Informações Básicas</h3>
<p>Código: {item.code}</p>
<p>Categoria: {item.category}</p>
<p>Status: {item.status}</p>
</div>
<div>
<h3>Descrição</h3>
<p>{item.description}</p>
</div>
</div>
<button onClick={() => setOpen(false)}>Fechar</button>
</div>
</Modal>
</>
);
}