6.2 KiB
6.2 KiB
Dialog — Padrão de Componente
Stack: Vue 3 + PrimeVue 4 + Tailwind CSS
Regras gerais
| Propriedade | Valor obrigatório |
|---|---|
modal |
sempre true |
maximizable |
sempre presente — botão nativo do PrimeVue, sem estado manual |
:draggable |
sempre false |
:closable |
!saving — desabilita o X durante operações assíncronas |
:dismissableMask |
!saving — impede fechar clicando fora durante saving |
pt:mask:class |
backdrop-blur-xs |
| Largura | w-[50rem] (padrão); responsivo via :breakpoints |
| Breakpoints | { '1199px': '90vw', '768px': '94vw' } |
Estrutura obrigatória
<Dialog>
├── #header ← dot de cor (se aplicável), título/subtítulo, btn Excluir
├── Banner ← preview visual (opcional — apenas quando há cor/identidade visual)
├── Corpo ← campos do formulário
└── #footer ← Cancelar (flat) | Salvar (primary)
Configuração completa do <Dialog>
<Dialog
v-model:visible="visible"
modal
:draggable="false"
:closable="!saving"
:dismissableMask="!saving"
maximizable
class="dc-dialog w-[50rem]"
:breakpoints="{ '1199px': '90vw', '768px': '94vw' }"
:pt="{
header: { class: '!p-3 !rounded-t-[12px] border-b border-[var(--surface-border)] shadow-[0_1px_0_0_rgba(255,255,255,0.06)] bg-gray-100' },
content: { class: '!p-3' },
footer: { class: '!p-0 !rounded-b-[12px] border-t border-[var(--surface-border)] shadow-[0_1px_0_0_rgba(255,255,255,0.06)] bg-gray-100' },
pcCloseButton: { root: { class: '!rounded-md hover:!text-red-500' } },
pcMaximizeButton: { root: { class: '!rounded-md hover:!text-primary' } },
}"
pt:mask:class="backdrop-blur-xs"
>
Detalhes do pt
| Chave | O que faz |
|---|---|
header |
!p-3 padding uniforme; !rounded-t-[12px] borda top arredondada; border-b + shadow separador com profundidade; bg-gray-100 fundo levemente cinza |
content |
!p-3 padding interno do corpo |
footer |
!p-0 remove padding nativo (controlado pelo wrapper interno); !rounded-b-[12px] borda bottom arredondada; border-t + shadow separador; bg-gray-100 fundo levemente cinza |
pcCloseButton |
!rounded-md remove o círculo nativo; hover:!text-red-500 feedback de danger no hover |
pcMaximizeButton |
!rounded-md remove o círculo nativo; hover:!text-primary feedback de cor primária no hover |
O
!(important) é necessário porque o PrimeVue injeta estilos inline nos botões e no root do Dialog — sem ele o Tailwind perde a disputa de especificidade.
Header — slot #header
[dot-cor] [título / subtítulo] [btn-excluir] ← Close e Maximize nativos vêm após
- O PrimeVue injeta Maximize e Close automaticamente à direita do slot
#header. - O botão Excluir fica sempre no header, nunca no footer.
- Excluir desabilitado quando o registro é nativo/padrão:
:disabled="saving || isNativeRecord".
<template #header>
<div class="flex w-full items-center justify-between gap-3 px-1">
<div class="flex items-center gap-3 min-w-0">
<!-- Dot de cor (omitir se não houver cor associada) -->
<span
class="shrink-0 w-3.5 h-3.5 rounded-full border-2 border-white/30
shadow-[0_0_0_3px_rgba(0,0,0,0.08)] transition-colors duration-200"
:style="{ backgroundColor: previewBgColor }"
/>
<div class="min-w-0">
<div class="text-base font-semibold truncate">
{{ form.name || (mode === 'create' ? 'Novo item' : 'Editar item') }}
</div>
<div class="text-xs opacity-50">
{{ mode === 'create' ? 'Criando novo registro' : 'Editando registro' }}
</div>
</div>
</div>
<div class="flex items-center gap-1 shrink-0">
<!-- Excluir — visível apenas em edit, desabilitado se nativo -->
<Button
v-if="mode === 'edit' && canDelete !== undefined"
icon="pi pi-trash"
severity="danger"
text
rounded
:disabled="saving || isNativeRecord"
v-tooltip.top="'Excluir'"
@click="emitDelete"
/>
<!-- Maximize e Close nativos do PrimeVue são injetados aqui automaticamente -->
</div>
</div>
</template>
Footer — slot #footer
<template #footer>
<div class="flex items-center justify-end gap-2 px-3 py-3">
<!-- Cancelar: sempre flat, hover vermelho suave -->
<Button
label="Cancelar"
severity="secondary"
text
class="rounded-full hover:!text-red-500"
:disabled="saving"
@click="close"
/>
<!-- Salvar: sempre primary -->
<Button
label="Salvar"
icon="pi pi-check"
class="rounded-full"
:loading="saving"
:disabled="!canSubmit"
@click="submit"
/>
</div>
</template>
Regra: Cancelar =
severity="secondary" text+hover:!text-red-500. Salvar = primary (sem severity, usa o padrão do tema). Padding controlado pelodivinterno (px-3 py-3), não pelopt.footer.
Maximizar
Use a prop nativa maximizable. O PrimeVue injeta e gerencia o botão automaticamente — sem ref, sem isMaximized, sem <Button> manual.
<Dialog maximizable ...>
Checklist antes de publicar um Dialog
modal,:draggable="false",:closable="!saving",:dismissableMask="!saving"presentesmaximizablena prop (botão nativo, sem estado manual)class="dc-dialog w-[50rem]"+:breakpoints="{ '1199px': '90vw', '768px': '94vw' }"ptcompleto: header, content, footer, pcCloseButton, pcMaximizeButton- Header com
bg-gray-100,border-b, shadow e!rounded-t-[12px] - Footer com
bg-gray-100,border-t, shadow e!rounded-b-[12px] - Botão Excluir no header (nunca no footer), desabilitado se nativo
- Cancelar =
text+hover:!text-red-500| Salvar = primary - Padding do footer via
px-3 py-3nodivinterno
Variações de largura
| Uso | Classe |
|---|---|
| Formulário simples | w-[36rem] |
| Formulário padrão | w-[50rem] ← padrão |
| Formulário complexo | w-[70rem] |
| Tela cheia | maximizable — usuário controla |