160 lines
5.4 KiB
Markdown
160 lines
5.4 KiB
Markdown
# DialogConfirmation — Padrão de Componente
|
|
|
|
> **Stack**: Vue 3 + PrimeVue 4 + Tailwind CSS
|
|
|
|
---
|
|
|
|
## Regras gerais
|
|
|
|
| Propriedade | Valor obrigatório |
|
|
|---|---|
|
|
| `group` | sempre `"headless"` — desacopla o template do trigger |
|
|
| `ConfirmDialog` | declarado **uma única vez**, no componente pai (página) |
|
|
| Filhos | disparam via `useConfirm()` com `group: 'headless'` — sem declarar `ConfirmDialog` próprio |
|
|
| `icon` | passado em `confirm.require({ icon })` — classe PrimeIcons sem o prefixo `pi` (ex: `'pi-trash'`) |
|
|
| `color` | passado em `confirm.require({ color })` — hex; define o fundo do círculo e a cor do botão Confirmar |
|
|
| `ConfirmationService` | obrigatório em `main.js` — `app.use(ConfirmationService)` |
|
|
|
|
---
|
|
|
|
## Arquitetura pai / filho
|
|
|
|
```
|
|
Pai (página)
|
|
└── <ConfirmDialog group="headless" /> ← único, renderiza aqui
|
|
├── Filho A (componente qualquer) → confirm.require({ group: 'headless', ... })
|
|
└── Filho B (Dialog interno) → confirm.require({ group: 'headless', ... })
|
|
```
|
|
|
|
> O `ConfirmDialog` **não** deve ser colocado dentro de um `<Dialog>` filho — isso causaria dois popups simultâneos. Sempre no pai.
|
|
|
|
---
|
|
|
|
## Setup obrigatório — `main.js`
|
|
|
|
```js
|
|
import ConfirmationService from 'primevue/confirmationservice'
|
|
|
|
app.use(ConfirmationService) // sem isso, useConfirm() não funciona
|
|
```
|
|
|
|
---
|
|
|
|
## Template do `ConfirmDialog` (somente no pai)
|
|
|
|
```vue
|
|
<!-- Declarado uma única vez, antes do conteúdo principal -->
|
|
<ConfirmDialog group="headless">
|
|
<template #container="{ message, acceptCallback, rejectCallback }">
|
|
<div class="flex flex-col items-center p-8 bg-surface-0 dark:bg-surface-900 rounded-xl shadow-xl">
|
|
|
|
<!-- Círculo central: cor e ícone vindos de message -->
|
|
<div
|
|
class="rounded-full inline-flex justify-center items-center h-24 w-24 -mt-20"
|
|
:style="{ background: message.color || 'var(--p-primary-color)', color: '#fff' }"
|
|
>
|
|
<i :class="`pi ${message.icon || 'pi-question'} !text-4xl`"></i>
|
|
</div>
|
|
|
|
<span class="font-bold text-2xl block mb-2 mt-6">{{ message.header }}</span>
|
|
<p class="mb-0 text-center text-[var(--text-color-secondary)]">{{ message.message }}</p>
|
|
|
|
<div class="flex items-center gap-2 mt-6">
|
|
<!-- Confirmar: cor dinâmica via message.color -->
|
|
<Button
|
|
label="Confirmar"
|
|
class="rounded-full"
|
|
:style="{
|
|
background: message.color || 'var(--p-primary-color)',
|
|
borderColor: message.color || 'var(--p-primary-color)'
|
|
}"
|
|
@click="acceptCallback"
|
|
/>
|
|
<!-- Cancelar: sempre outlined, neutro -->
|
|
<Button
|
|
label="Cancelar"
|
|
variant="outlined"
|
|
class="rounded-full"
|
|
@click="rejectCallback"
|
|
/>
|
|
</div>
|
|
|
|
</div>
|
|
</template>
|
|
</ConfirmDialog>
|
|
```
|
|
|
|
---
|
|
|
|
## Uso nos componentes (pai ou filhos)
|
|
|
|
```vue
|
|
<script setup>
|
|
import { useConfirm } from 'primevue/useconfirm'
|
|
const confirm = useConfirm()
|
|
|
|
function confirmDelete(item) {
|
|
confirm.require({
|
|
group: 'headless',
|
|
header: 'Excluir item?',
|
|
message: `"${item.name}" será removido permanentemente. Essa ação não pode ser desfeita.`,
|
|
icon: 'pi-trash',
|
|
color: '#ef4444',
|
|
accept: () => onDelete(item)
|
|
})
|
|
}
|
|
</script>
|
|
```
|
|
|
|
---
|
|
|
|
## Paleta de ícones e cores por ação
|
|
|
|
| Ação | `icon` | `color` | Observação |
|
|
|---|---|---|---|
|
|
| Excluir / Remover | `pi-trash` | `#ef4444` | Vermelho — ação destrutiva |
|
|
| Salvar / Confirmar | `pi-save` | `var(--p-primary-color)` | Cor primária do tema |
|
|
| Editar / Atualizar | `pi-pencil` | `#f97316` | Laranja — mudança de estado |
|
|
| Aviso / Atenção | `pi-exclamation-triangle` | `#eab308` | Amarelo — ação reversível |
|
|
| Info / Neutro | `pi-info-circle` | `#3b82f6` | Azul — informativo |
|
|
|
|
---
|
|
|
|
## Referência completa de `confirm.require`
|
|
|
|
```js
|
|
confirm.require({
|
|
group: 'headless', // obrigatório — aponta para o ConfirmDialog correto
|
|
header: 'Título do popup', // linha em negrito
|
|
message: 'Descrição clara.', // linha secundária
|
|
icon: 'pi-trash', // sufixo PrimeIcons sem o "pi " inicial
|
|
color: '#ef4444', // hex — fundo do círculo + cor do botão Confirmar
|
|
accept: () => { /* ação confirmada */ },
|
|
reject: () => { /* opcional — ação cancelada */ }
|
|
})
|
|
```
|
|
|
|
---
|
|
|
|
## Checklist antes de usar
|
|
|
|
- [ ] `ConfirmationService` registrado no `main.js`
|
|
- [ ] `<ConfirmDialog group="headless">` declarado **apenas no pai**, antes do conteúdo
|
|
- [ ] Filhos usam `useConfirm()` com `group: 'headless'` — sem `ConfirmDialog` próprio
|
|
- [ ] `icon` passado como sufixo PrimeIcons: `'pi-trash'`, não `'pi pi-trash'`
|
|
- [ ] `color` em hex para ações com semântica de cor (delete = `#ef4444`)
|
|
- [ ] `header` curto e direto | `message` com contexto suficiente para o usuário decidir
|
|
- [ ] `accept` contém a ação real — `reject` é opcional
|
|
|
|
---
|
|
|
|
## Variações de confirmação
|
|
|
|
| Contexto | `header` | `icon` | `color` |
|
|
|---|---|---|---|
|
|
| Excluir registro | `'Excluir <entidade>?'` | `pi-trash` | `#ef4444` |
|
|
| Remover item de lista | `'Remover campo?'` | `pi-trash` | `#ef4444` |
|
|
| Salvar com impacto | `'Confirmar alterações?'` | `pi-save` | primária |
|
|
| Atualizar com risco | `'Atualizar <entidade>?'` | `pi-pencil` | `#f97316` |
|
|
| Ação irreversível genérica | `'Tem certeza?'` | `pi-exclamation-triangle` | `#eab308` |
|