Modal
Componente standalone com CDK Overlay/Portal/A11y, focus trap, backdrop, Escape e retorno de foco.
Design
Anatomia
Review changes 4
Check the details before applying this update.
The update can be reverted later from the activity log.
6.ds-modal-overlay) — backdrop em tela cheia que bloqueia interação com a página.2 Container (
.ds-modal) — superfície elevada com border-radius e sombra.3 Header (
.ds-modal__header) — contém heading opcional, descrição e button de fechar.4 Título (
.ds-modal__title) — vinculado via aria-labelledby.5 Button de fechar (
.ds-modal__close) — dispensa o modal.6 Corpo (
.ds-modal__body) — área de conteúdo com scroll.7 Rodape (
.ds-modal__footer) — buttons de ação alinhados a direita.
Exemplo interativo · Angular
Executado pelo componente Angular nativo com @angular/cdk/overlay + portal + a11y.
Tamanhos · Angular
Três dialogs independentes executados pelo componente Angular com CDK Overlay.
Body customizado · Angular
Content projection com Form Field, Input e Buttons públicos dentro do Overlay Angular.
Mapeamento de tokens
| Propriedade | Token | Variável CSS |
|---|---|---|
| overlay background | component.modal.overlay.bg.default | --ds-modal-overlay-bg-default |
| surface | semantic.surface.elevated | --ds-surface-elevated |
| overlay padding | component.modal.overlay.padding.default | --ds-modal-overlay-padding-default |
| overlay z-index | component.modal.overlay.z-index.default | --ds-modal-overlay-z-index-default |
| border-radius | component.modal.radius.default | --ds-modal-radius-default |
| shadow | component.modal.shadow.default | --ds-modal-shadow-default |
| max-width | component.modal.max-width.{sm,md,lg} | --ds-modal-max-width-* |
| header spacing | component.modal.header.{padding-*,gap}.* | --ds-modal-header-*-* |
| body spacing/typography | component.modal.body.{padding-*,font-size,line-height,font-weight}.* | --ds-modal-body-*-* |
| description typography | component.modal.body.{font-size,line-height,font-weight}.* | --ds-modal-body-*-* |
| title typography | component.modal.title.{font-size,line-height,font-weight,letter-spacing}.* | --ds-modal-title-*-* |
| footer spacing | component.modal.footer.{padding-*,gap}.* | --ds-modal-footer-*-* |
| close target | component.modal.close.size.{sm,md,lg} | --ds-modal-close-size-* |
| close icon | component.modal.close.icon-size.{sm,md,lg} | --ds-modal-close-icon-size-* |
| close padding | component.modal.close.padding.{sm,md,lg} | --ds-modal-close-padding-* |
Uso
Quando usar
- Uma edição curta ou revisão precisa terminar antes de retornar ao contexto anterior.
- O conteúdo exige atenção concentrada, mas ainda não justifica uma página dedicada.
Quando não usar
- A tarefa é longa, possui várias etapas ou precisa continuar visível junto da página.
- A confirmação é destrutiva ou crítica; esse caso pertence ao contrato separado de Alert Dialog.
Quando escolher esta saída
Adote esta saída Angular nativa quando a aplicação já usa Angular. Ela consome o mesmo CSS do DS e não depende do runtime Web nem dos adapters React.
Implementação
- Status
- Beta
- Distribuição
- Tarball Angular validado
Instalação
npm install ./dist/tis-angular-0.0.0-beta.0.tgz ds-tispnpm add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisyarn add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisbun add ./dist/tis-angular-0.0.0-beta.0.tgz ds-tisEstilos do DS
@import "ds-tis/css";Importações Angular
import { TisButton } from '@tis/angular/button'
import {
TisModal,
TisModalBody,
TisModalFooter,
TisModalInitialFocus,
} from '@tis/angular/modal'Template
<tis-button (click)="modalOpen.set(true)">Revisar alterações</tis-button>
<tis-modal
#modal
title="Revisar alterações"
description="Confira os dados antes de continuar."
size="md"
[open]="modalOpen()"
(openChange)="modalOpen.set($event)"
>
<div tisModalBody>Conteúdo curto da tarefa.</div>
<div tisModalFooter>
<tis-button (click)="modal.close('api')">Guardar</tis-button>
</div>
</tis-modal>Contrato público
- Pacote
@tis/angular- Entrypoint
@tis/angular/modal- Primitive
@angular/cdk/overlay + portal + a11y- Status
- Beta
Acessibilidade
Interação por teclado
| Tecla | Ação |
|---|---|
Tab | Cicla o foco dentro do modal (focus trap) |
Shift+Tab | Cicla o foco para tras dentro do modal |
Escape | Fecha o modal |
Enter | Ativa o button focado |
O foco deve ser preso dentro do modal enquanto estiver aberto. Quando o modal fechar, o foco deve retornar ao elemento que o disparou.
Accessibility
| Critério WCAG | Requisito | Status |
|---|---|---|
| 2.4.3 Focus Order (A) | O foco move para dentro do modal ao abrir, fica preso dentro e retorna ao trigger ao fechar | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring visível em todos os elementos interativos dentro do modal | ✓ |
| 4.1.2 Name, Role, Value (A) | role="dialog", aria-modal="true", aria-labelledby apontando para o título | ✓ |
| 1.4.11 Non-text Contrast (AA) | Button de fechar tem pelo menos 3:1 de ratio de contraste contra a superfície do modal | ✓ |
role="dialog" — identifica o modal como um diálogo.aria-modal="true" — informa a tecnologia assistiva que o conteúdo atras do modal esta inerte.aria-labelledby — referencia o id do elemento de título do modal.aria-label="Close modal" — obrigatorio no button de fechar.
Responsabilidade da saída
Preserve o contrato de dialog modal e valide focus trap, Escape, dismiss pelo backdrop, bloqueio de scroll, relações ARIA e retorno de foco.
Evidência de validação
Coberta pelo Storybook da saída independente e por verificações de browser, responsividade, teclado, Axe e bundle.