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:
| Tamanho | Largura | Uso recomendado |
|---|---|---|
sm | 420px | Confirmações simples e alertas |
md | 540px | Formulários e conteúdo geral (padrão) |
lg | 660px | Conteúdo extenso e formulários complexos |
xl | 780px | Conteúdo muito extenso e tabelas |
Modal em bloco
Modal que se estende até a largura máxima disponível:
Modal sem botão fechar
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
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
children | ReactNode | - | Conteúdo a ser exibido dentro do modal |
isOpen | boolean | - | Controla se o modal está aberto |
onRequestClose | (event: MouseEvent | KeyboardEvent) => void | - | Função chamada quando o modal é solicitado para fechar |
blocked | boolean | false | Se true, o modal se estende até a largura máxima |
maxWidth | 'sm' | 'md' | 'lg' | 'xl' | false | false | Determina a largura máxima do modal |
disableClose | boolean | false | Desabilita o botão de fechar |
contentLabel | string | - | Label para acessibilidade do conteúdo do modal |
ariaHideApp | boolean | true | Controla se deve esconder a aplicação do screen reader |
closeTimeoutMS | number | 150 | Tempo 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:
| Classe | Descrição |
|---|---|
.ods-modal | Container portal do modal |
.ods-modal__overlay | Overlay de fundo do modal |
.ods-modal__overlay--after-open | Modificador para overlay após abertura |
.ods-modal__overlay--before-close | Modificador para overlay antes do fechamento |
.ods-modal__content | Container principal do conteúdo do modal |
.ods-modal__content--after-open | Modificador para conteúdo após abertura |
.ods-modal__content--before-close | Modificador para conteúdo antes do fechamento |
.ods-modal__content--sm | Modificador para modal de tamanho pequeno |
.ods-modal__content--md | Modificador para modal de tamanho médio |
.ods-modal__content--lg | Modificador para modal de tamanho grande |
.ods-modal__content--xl | Modificador para modal de tamanho extra grande |
.ods-modal__content--blocked | Modificador para modal bloqueado |
.ods-modal__header | Cabeçalho do modal |
.ods-modal__header-close | Botão de fechar do modal |
.ods-modal__body | Corpo 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
contentLabelpara identificação
Navegação por teclado
| Tecla | Função |
|---|---|
Escape | Fecha o modal |
Tab | Navega 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
contentLabeldescritivo - 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
Modal de confirmação
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>
</>
);
}
Modal de formulário
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>
</>
);
}
Modal de detalhes
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>
</>
);
}
Links relacionados
- Drawer - Para conteúdo lateral que não bloqueia a interação
- ContextualMenu - Para menus de opções contextuais
- Alert - Para notificações simples inline
- Snackbar - Para feedback temporário
- Storybook - Modal - Documentação técnica