Makuco UI
ComponentesGeneral

Dialog

Janela modal para foco em uma tarefa ou informação crítica, com trap de foco e suporte a teclado.

O mk-dialog renderiza um painel modal sobre um backdrop que bloqueia a interação com o restante da página até que o usuário tome uma decisão ou o dispense. Gerencia foco automaticamente (trap de foco, restauração ao fechar) e suporta fechamento via tecla Escape, clique no backdrop e botão X. A composição é feita com três subcomponentes: mk-dialog-header, mk-dialog-body e mk-dialog-footer. Por interromper o fluxo da interface, deve ser usado com parcimônia — cada abertura de dialog representa uma quebra de contexto para o usuário.

Quando usar

O dialog é adequado quando a tarefa exige atenção total antes de prosseguir.

Use quando:
  • O usuário precisa confirmar uma ação antes que ela seja executada, especialmente ações destrutivas.
  • Um formulário curto precisa ser preenchido sem navegar para outra página.
  • Informações críticas precisam ser lidas ou reconhecidas antes de continuar.
Prefira uma alternativa quando:
  • O conteúdo for extenso — use uma página ou drawer dedicado.
  • A informação for apenas notificacional e não exigir resposta — use um mk-toast.
  • O contexto puder ser preservado com um painel lateral.

Anatomia

O dialog é composto por três regiões empilhadas verticalmente, cada uma representada por um subcomponente dedicado.

#SubcomponenteObrigatório?Função
1mk-dialog-headerSimCabeçalho do dialog. Aceita texto simples como título ou conteúdo customizado. O botão de fechar (×) é renderizado automaticamente pelo mk-dialog.
2mk-dialog-bodySimÁrea de conteúdo flexível para texto explicativo, formulários ou qualquer conteúdo relevante.
3mk-dialog-footerNãoRodapé de ações. Alinha os botões horizontalmente com justify-content: flex-end automaticamente.

Padrão

A estrutura completa usa mk-dialog-header, mk-dialog-body e mk-dialog-footer como filhos diretos de mk-dialog.

import { useState } from 'react';
import { MkDialog, MkDialogHeader, MkDialogBody, MkDialogFooter, MkButton } from '@db1/makuco-ui-react';

function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <MkButton onMkClick={() => setOpen(true)}>Abrir dialog</MkButton>
      <MkDialog open={open} onMkClose={() => setOpen(false)}>
        <MkDialogHeader>Confirmar ação</MkDialogHeader>
        <MkDialogBody>
          <p>Tem certeza que deseja continuar?</p>
        </MkDialogBody>
        <MkDialogFooter>
          <MkButton variant="outlined" onMkClick={() => setOpen(false)}>Cancelar</MkButton>
          <MkButton onMkClick={handleConfirm}>Confirmar</MkButton>
        </MkDialogFooter>
      </MkDialog>
    </>
  );
}
<mk-button (mkClick)="open = true">Abrir dialog</mk-button>

<mk-dialog [open]="open" (mkClose)="open = false">
  <mk-dialog-header>Confirmar ação</mk-dialog-header>
  <mk-dialog-body>
    <p>Tem certeza que deseja continuar?</p>
  </mk-dialog-body>
  <mk-dialog-footer>
    <mk-button variant="outlined" (mkClick)="open = false">Cancelar</mk-button>
    <mk-button (mkClick)="handleConfirm()">Confirmar</mk-button>
  </mk-dialog-footer>
</mk-dialog>

Ação destrutiva

Para ações de alto risco, use kind="destructive" no botão de confirmação. O header pode receber conteúdo customizado com ícone via mk-dialog-header.

<MkDialog open={open} onMkClose={() => setOpen(false)}>
  <MkDialogHeader>Excluir registro</MkDialogHeader>
  <MkDialogBody>
    <p>Esta ação é permanente. O registro será removido e não poderá ser recuperado.</p>
  </MkDialogBody>
  <MkDialogFooter>
    <MkButton variant="outlined" onMkClick={() => setOpen(false)}>Cancelar</MkButton>
    <MkButton kind="destructive" onMkClick={handleDelete}>Excluir</MkButton>
  </MkDialogFooter>
</MkDialog>
<mk-dialog [open]="open" (mkClose)="open = false">
  <mk-dialog-header>Excluir registro</mk-dialog-header>
  <mk-dialog-body>
    <p>Esta ação é permanente. O registro será removido e não poderá ser recuperado.</p>
  </mk-dialog-body>
  <mk-dialog-footer>
    <mk-button variant="outlined" (mkClick)="open = false">Cancelar</mk-button>
    <mk-button kind="destructive" (mkClick)="handleDelete()">Excluir</mk-button>
  </mk-dialog-footer>
</mk-dialog>

Tamanhos

<MkDialog open={open} size="sm" onMkClose={() => setOpen(false)}>
  <MkDialogHeader>Dialog SM</MkDialogHeader>
  <MkDialogBody>...</MkDialogBody>
</MkDialog>

<MkDialog open={open} size="lg" onMkClose={() => setOpen(false)}>
  <MkDialogHeader>Dialog LG</MkDialogHeader>
  <MkDialogBody>...</MkDialogBody>
</MkDialog>
<mk-dialog [open]="open" size="sm" (mkClose)="open = false">
  <mk-dialog-header>Dialog SM</mk-dialog-header>
  <mk-dialog-body>...</mk-dialog-body>
</mk-dialog>

<mk-dialog [open]="open" size="lg" (mkClose)="open = false">
  <mk-dialog-header>Dialog LG</mk-dialog-header>
  <mk-dialog-body>...</mk-dialog-body>
</mk-dialog>

Sem fechar no backdrop

<MkDialog open={open} closeOnBackdrop={false} onMkClose={() => setOpen(false)}>
  <MkDialogHeader>Ação obrigatória</MkDialogHeader>
  <MkDialogBody>
    <p>Você precisa tomar uma decisão para fechar este dialog.</p>
  </MkDialogBody>
  <MkDialogFooter>
    <MkButton variant="outlined" onMkClick={() => setOpen(false)}>Cancelar</MkButton>
    <MkButton onMkClick={handleConfirm}>Confirmar</MkButton>
  </MkDialogFooter>
</MkDialog>
<mk-dialog [open]="open" [close-on-backdrop]="false" (mkClose)="open = false">
  <mk-dialog-header>Ação obrigatória</mk-dialog-header>
  <mk-dialog-body>
    <p>Você precisa tomar uma decisão para fechar este dialog.</p>
  </mk-dialog-body>
  <mk-dialog-footer>
    <mk-button variant="outlined" (mkClick)="open = false">Cancelar</mk-button>
    <mk-button (mkClick)="handleConfirm()">Confirmar</mk-button>
  </mk-dialog-footer>
</mk-dialog>

Header personalizado

Passe conteúdo customizado dentro de mk-dialog-header para substituir o título por texto enriquecido, ícone ou qualquer markup.

import { MkDialog, MkDialogHeader, MkDialogBody, MkDialogFooter, MkButton, MkIcon } from '@db1/makuco-ui-react';

<MkDialog open={open} onMkClose={() => setOpen(false)}>
  <MkDialogHeader>
    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
      <MkIcon name="triangle-alert" size="md" />
      <span className="mk-typography-heading-sm-semi-bold">Ação destrutiva</span>
    </div>
  </MkDialogHeader>
  <MkDialogBody>
    <p>Esta ação não pode ser desfeita. Tem certeza que deseja continuar?</p>
  </MkDialogBody>
  <MkDialogFooter>
    <MkButton variant="outlined" onMkClick={() => setOpen(false)}>Cancelar</MkButton>
    <MkButton kind="destructive" onMkClick={handleConfirm}>Confirmar</MkButton>
  </MkDialogFooter>
</MkDialog>
<mk-dialog [open]="open" (mkClose)="open = false">
  <mk-dialog-header>
    <div style="display: flex; align-items: center; gap: 8px;">
      <mk-icon name="triangle-alert" size="md"></mk-icon>
      <span class="mk-typography-heading-sm-semi-bold">Ação destrutiva</span>
    </div>
  </mk-dialog-header>
  <mk-dialog-body>
    <p>Esta ação não pode ser desfeita. Tem certeza que deseja continuar?</p>
  </mk-dialog-body>
  <mk-dialog-footer>
    <mk-button variant="outlined" (mkClick)="open = false">Cancelar</mk-button>
    <mk-button kind="destructive" (mkClick)="handleConfirm()">Confirmar</mk-button>
  </mk-dialog-footer>
</mk-dialog>

Comportamento

O dialog abre sobre um overlay escurecido que bloqueia a interação com o conteúdo ao fundo. Ao abrir, o foco é movido automaticamente para dentro do painel. O usuário pode fechar o dialog pelo botão ×, pelos botões do footer, clicando no backdrop (quando closeOnBackdrop está habilitado) ou pressionando Escape. Ao fechar, o foco retorna ao elemento que originou a abertura.

Composição

Use mk-button com variant="filled" para a ação principal no mk-dialog-footer e variant="outlined" para cancelar. Para ações destrutivas, aplique kind="destructive" no botão de confirmação para reforçar o risco da operação ao usuário.

O mk-dialog-footer aplica automaticamente display: flex, justify-content: flex-end e gap entre os botões — não é necessário adicionar um elemento wrapper.

Props — mk-dialog

PropTipoPadrãoDescrição
openbooleanfalseControla a visibilidade do dialog.
size"sm" | "md" | "lg" | "xl""md"Controla o max-width do painel.
closeOnBackdropbooleantrueFecha o dialog ao clicar no backdrop.
hideClosebooleanfalseOculta o botão X do cabeçalho.
headingstringAtalho para título simples sem usar mk-dialog-header. Ignorado quando mk-dialog-header é fornecido.
localestringTag BCP 47 para i18n ("en", "pt-BR"). Recai para o lang do ancestral mais próximo.

Eventos

EventoPayloadDescrição
mkClosevoidEmitido ao fechar via botão X, clique no backdrop ou tecla Escape.

Subcomponentes

TagSlot atribuídoDescrição
mk-dialog-headerheaderRenderiza o conteúdo no cabeçalho do dialog. Atribui slot="header" automaticamente quando filho direto de mk-dialog. Aceita texto simples ou markup customizado.
mk-dialog-body(default)Renderiza o conteúdo no corpo do dialog. Adiciona padding e tipografia padrão do corpo.
mk-dialog-footerfooterRenderiza o rodapé de ações. Atribui slot="footer" automaticamente quando filho direto de mk-dialog. Aplica flex, justify-content: flex-end e gap internamente.

Acessibilidade

  • role="dialog" e aria-modal="true" aplicados no painel.
  • aria-labelledby aponta para o conteúdo de mk-dialog-header quando presente, para que leitores de tela anunciem o contexto ao abrir.
  • Trap de foco ativo enquanto o dialog estiver aberto — Tab e Shift+Tab cicla entre elementos focáveis.
  • Escape fecha o dialog e restaura o foco ao elemento que o abriu.
  • body recebe overflow: hidden enquanto o dialog estiver aberto.

Trap de foco: enquanto o dialog estiver aberto, o Tab deve circular apenas pelos elementos dentro dele — o usuário não deve conseguir focar elementos da página ao fundo.

Overlay: o conteúdo ao fundo deve ser marcado como inerte (aria-hidden="true") enquanto o dialog estiver aberto, evitando que leitores de tela naveguem por ele.

On this page