Dialog Message para Quasar
🇺🇸 English | 🇧🇷 Versão em português
Extensión Quasar para diálogos modales de mensaje (alertas y confirmación) en apps Vue 3 + Quasar, con API imperativa basada en composable.
Tabla de contenidos
- En 30 segundos
- Qué es y qué incluye
- Requisitos y compatibilidad
- Instalación en app Quasar
- Qué agrega la extensión al host
- Defaults globales (boot)
- Idioma (i18n)
- Uso rápido
- TypeScript en tu IDE
- API pública
- Presets visuales
- Icono y botones por tema
- Alertas vs confirmación
- Tipos TypeScript exportados
- Entrypoints públicos
- Troubleshooting
En 30 segundos
Flujo base recomendado:
- Instalar la extensión en tu app Quasar (
quasar ext add). - Asegurar que el boot de Pinia del host corre antes que el boot de esta extensión.
- Importar
useDialogMessage()donde muestres feedback al usuario. - Llamar
await message.success()(preset i18n) oawait message.success({ text: '...' }); confirm:const ok = await message.confirm({ text: '...' }).
La extensión registra boots y CSS en el proyecto host automáticamente tras quasar ext add.
Qué es y qué incluye
Diálogo modal global controlado por useDialogMessage() — no es un componente embebible.
- Presets de alerta —
success,info,warn,error(un botón Aceptar). - Confirmación —
confirm()con dos botones (Cancelar / Confirmar) yPromise<boolean>. - Defaults por preset en boot del host (
title,icon,iconColor, labels). - i18n built-in
en,es,pt— presets y botones siguen$q.lang; overrides en boot (locale,messages,presets). - Tema light / dark —
iconColor: { light, dark }ybuttonStyleglobal o por preset. - Override por llamada —
title,text,icon, colores, variantes de botón y labels. onAccept/onCancel— side-effects opcionales al pulsar botones.hide()— cierre imperativo sin ejecutar callbacks.persistent— impide cerrar con backdrop o Esc (configurable en boot).
Requisitos y compatibilidad
| Item | Valor |
|---|---|
| Node | >= 20.0.0 |
| Quasar | ^2.6.0 |
| Vue | ^3.4.18 |
| Pinia | ^2.0.11 | ^3.0.0 |
| Formato del paquete | ES modules |
| CLI recomendado | @quasar/app-vite ^2.x o ^3.x |
El boot de Pinia del host debe ejecutarse antes del boot de esta extensión.
Instalación en app Quasar
quasar ext add @benjaminor-dev/dialog-message
Remover:
quasar ext remove @benjaminor-dev/dialog-message
Tras quasar ext add, la extensión registra boots y CSS en tu app automáticamente. No necesitas pasos adicionales en una instalación normal desde npm.
Qué agrega la extensión al host
Recursos que instala o registra la extensión:
| Recurso | Ruta npm |
|---|---|
| Boot del diálogo | ~@benjaminor-dev/quasar-app-extension-dialog-message/boot/dialog |
| Estilos | ~@benjaminor-dev/quasar-app-extension-dialog-message/main.css |
| Defaults boot (host) | src/boot/bor/bor-dialog-message-defaults.ts — creado en install; Skip/Overwrite si ya existe |
Install (quasar ext add / invoke): crea src/boot/bor/bor-dialog-message-defaults.ts (o .js) y lo registra en quasar.config → boot: [] automáticamente. No hace falta editarlo a mano en una instalación normal. El boot de paquete (boot/dialog) y main.css los inyecta la extensión en cada dev/build (no aparecen como entradas cortas en quasar.config).
Remove (quasar ext remove): elimina el defaults boot y su entrada en quasar.config.
Orden de boots mínimo:
1. Pinia (host)
2. Dialog Message — boot/dialog
3. bor/bor-dialog-message-defaults (host)
En quasar.config solo verás bor/bor-dialog-message-defaults; el boot boot/dialog lo añade el runner al compilar.
El boot monta el diálogo en el documento y conecta la store de Pinia del host. No necesitas importar DialogMessage en App.vue.
Defaults globales (boot)
Evita repetir títulos, iconos, labels y medidas en cada llamada. Prioridad: opciones por llamada → boot del host → i18n (locale / $q.lang / en).
Tras quasar ext add, revisa src/boot/bor/bor-dialog-message-defaults.ts — plantilla con instrucciones de idioma en el comentario del archivo.
// src/boot/bor/bor-dialog-message-defaults.ts
import { configureDialogMessageDefaults } from "@benjaminor-dev/quasar-app-extension-dialog-message";
configureDialogMessageDefaults({
// locale: "es", // descomenta para fijar un idioma concreto en Dialog Message
width: "420px",
persistent: true,
zIndex: 7000,
gap: "1rem",
actionsGap: "2rem",
font: {
family: "Arial, sans-serif",
sizeTitle: "1.4rem",
sizeText: "1.2rem",
},
buttonStyle: {
light: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "primary",
cancelVariant: "outline",
},
dark: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "white",
cancelVariant: "outline",
},
},
});
Idioma (i18n)
Built-in en, es y pt para títulos, textos y labels de presets (success, info, warn, error, confirm). Por defecto sigue $q.lang; sin idioma Quasar, cae en en.
Resolución de locale: boot locale → prefijo de $q.lang.isoName (es* → es, pt* → pt) → en.
Resolución de textos: opciones por llamada → boot presets.<variant> → boot messages → catálogo built-in → en. Iconos y colores default vienen de visuales built-in; override visual en boot presets.
| Opción | Cuándo usarla |
|---|---|
framework.lang en quasar.config.ts |
Recomendado — alinea Dialog Message con Quasar |
locale: 'es' en boot |
Fijar un idioma concreto (en | es | pt); ignora cambios de $q.lang |
messages / presets en boot |
Override parcial (un preset o un label) |
Ejemplo español en toda la app:
// quasar.config.ts
framework: {
lang: "es",
},
Override de un preset (visual + texto):
configureDialogMessageDefaults({
presets: {
confirm: { title: "¿Eliminar registro?", acceptLabel: "Eliminar" },
},
});
Override i18n sin cambiar iconos:
configureDialogMessageDefaults({
messages: {
acceptLabel: "Entendido",
presets: { warn: { title: "Atención", text: "Revisa los datos" } },
},
});
configureDialogMessage es alias de configureDialogMessageDefaults.
| Opción boot | Default built-in | Descripción |
|---|---|---|
locale |
(sigue $q.lang) |
Fija en | es | pt para textos de presets |
messages |
(por locale) | Override parcial i18n (presets.success.title, …) |
acceptLabel |
"OK" (i18n) |
Fallback global del botón Aceptar |
cancelLabel |
"No" (i18n) |
Fallback global del botón Cancelar en confirm |
width |
"420px" |
Ancho máximo de la card |
persistent |
true |
Bloquea cierre con backdrop / Esc |
zIndex |
7000 |
Capa del diálogo respecto al resto de la UI |
gap |
"1rem" |
Espacio icono ↔ título ↔ texto |
actionsGap |
"2rem" |
Espacio bloque de texto ↔ botones |
font.sizeTitle |
"1.4rem" |
CSS font-size del título |
font.sizeText |
"1.2rem" |
CSS font-size del cuerpo |
font.family |
"Arial, sans-serif" |
CSS font-family del título y texto |
buttonStyle |
Ver boot plantilla | Colores y variantes de botones por tema (light / dark) |
presets.<variant> |
(i18n + iconos) | Override de title, text, icon, iconColor, labels |
Cada preset incluye title, text y labels por idioma. Override en boot solo si necesitas personalizar iconos o textos de dominio.
Variantes de preset: success, info, warn, error, confirm.
Prioridad por campo: llamada → preset (boot) → i18n → global (boot). Dentro de botones, buttonStyle.<tema> gana sobre acceptColor / cancelColor planos del mismo nivel.
Uso rápido
<script setup lang="ts">
import { useDialogMessage } from "@benjaminor-dev/quasar-app-extension-dialog-message";
const message = useDialogMessage();
async function onSave() {
try {
await api.save(formData);
await message.success(); // preset i18n (title + text)
// await message.success({ text: "Se ha guardado el registro" });
} catch (error) {
await message.error({ text: "No se pudo guardar" });
}
}
async function onDelete(item: { id: string }) {
const confirmed = await message.confirm({
title: "Eliminar registro",
text: "Se eliminará el registro seleccionado. ¿Deseas continuar?",
});
if (!confirmed) return;
await api.delete(item.id);
await message.success({ text: "Registro eliminado" });
}
</script>
<template>
<q-btn label="Guardar" @click="onSave" />
<q-btn label="Eliminar" color="negative" @click="onDelete({ id: '1' })" />
</template>
Alerta con override puntual de título e icono:
await message.info({
title: "Aviso importante",
text: "Revisa los datos antes de continuar",
icon: "campaign",
iconColor: "warning",
});
Confirm con override de botones solo en dark:
const ok = await message.confirm({
text: "¿Deseas continuar?",
buttonStyle: {
dark: { cancelColor: "grey-4" },
},
});
if (!ok) return;
Side-effect al aceptar (p. ej. logout):
await message.warn({
text: "Tu sesión expirará en 5 minutos",
onAccept: async () => {
await auth.refreshSession();
},
});
TypeScript en tu IDE
No memorices la API: deja que el autocompletado te guíe.
useDialogMessage()devuelveDialogMessageApi— métodos y refs aparecen al escribirmessage..- En
configureDialogMessageDefaults({ ... }), Ctrl+Space / Cmd+Space listapresets,buttonStyle,gap,font,zIndex, etc. - Dentro de
presets.success,presets.confirm, etc., el IDE sugieretitle,text,icon,iconColor,acceptLabel,cancelLabel,buttonStyle. - En
font, el IDE sugierefamily,sizeTitle,sizeText. iconColoracepta string plano o{ light, dark };buttonStyleagrupa colores y variantes de botones por tema.success/info/warn/erroraceptanDialogMessageOptions;confirmaceptaDialogMessageConfirmOptions(añadecancelLabel,cancelColor,cancelVariant,onCancel).confirm()resuelvePromise<boolean>; los presets de alerta resuelvenPromise<void>al pulsar Aceptar.- Pasa el cursor sobre un método: el tooltip muestra parámetros y JSDoc.
Si algo no aparece en autocompletado, suele ser una prop inexistente o un import incorrecto — revisa el entrypoint principal antes de buscar en el README.
API pública
Punto de entrada: useDialogMessage().
import { useDialogMessage } from "@benjaminor-dev/quasar-app-extension-dialog-message";
const message = useDialogMessage();
Métodos
| Método | Retorno | Descripción |
|---|---|---|
success(options?) |
Promise<void> |
Alerta de éxito (preset success; options opcional) |
info(options?) |
Promise<void> |
Alerta informativa |
warn(options?) |
Promise<void> |
Alerta de advertencia |
error(options?) |
Promise<void> |
Alerta de error |
confirm(options?) |
Promise<boolean> |
Confirmación con dos botones; true = confirmar |
hide() |
void |
Cierra sin onAccept; en confirm resuelve false |
Estado reactivo (solo lectura)
| Ref | Descripción |
|---|---|
visible |
Si el diálogo está visible |
Opciones por llamada (DialogMessageOptions)
| Campo | Descripción |
|---|---|
title? |
Título; omite → preset del boot; "" oculta el título |
text? |
Cuerpo del mensaje |
icon? |
Icono Material Icons (Quasar) |
iconColor? |
Color del icono: string o { light?, dark? } |
acceptLabel? |
Label del botón principal |
acceptColor? |
Color Quasar del botón principal (plano; ambos temas) |
acceptVariant? |
Variante Quasar: flat | outline | unelevated | push |
buttonStyle? |
Override parcial { light?, dark? } de colores/variantes de botones |
onAccept? |
Callback al pulsar Aceptar / Confirmar |
DialogMessageConfirmOptions extiende lo anterior con:
| Campo | Descripción |
|---|---|
cancelLabel? |
Label del botón Cancelar |
cancelColor? |
Color Quasar del botón Cancelar (plano) |
cancelVariant? |
Variante Quasar del botón Cancelar |
onCancel? |
Callback al pulsar Cancelar |
Presets visuales
Configura cada preset en presets del boot (o usa los built-in).
| Preset | Uso típico | Icono default | Color default |
|---|---|---|---|
success |
Operación completada | check_circle |
positive |
info |
Aviso neutral | info |
primary |
warn |
Atención / precaución | warning |
warning |
error |
Fallo o error | error |
negative |
confirm |
Pregunta sí/no antes de actuar | back_hand |
primary |
Constante exportada: DIALOG_MESSAGE_VARIANTS — lista de variantes válidas.
Icono y botones por tema
El diálogo resuelve colores según $q.dark.isActive (light / dark).
Icono — iconColor
En boot (por preset) o por llamada:
iconColor: { light: "negative", dark: "red-4" }
// o plano (mismo color en ambos temas):
iconColor: "positive"
Botones — buttonStyle
Global en boot (aplica a todos los presets) o parcial por preset / llamada:
buttonStyle: {
light: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "primary",
cancelVariant: "outline",
},
dark: {
acceptColor: "primary",
acceptVariant: "unelevated",
cancelColor: "white",
cancelVariant: "outline",
},
}
Campos por tema en buttonStyle: acceptColor, acceptVariant, cancelColor, cancelVariant.
Built-in de variantes: Aceptar → unelevated, Cancelar → outline.
Alertas vs confirmación
| Aspecto | Alertas (success … error) |
Confirm (confirm) |
|---|---|---|
| Botones | Uno (Aceptar) | Dos (Cancelar + Confirmar) |
| Promise | void al aceptar |
boolean (true / false) |
| Orden UX (LTR) | — | Cancelar izquierda, Confirmar derecha |
hide() |
Cierra sin callback | Resuelve false |
| Labels default | presets.<variant>.acceptLabel (p. ej. "OK") |
presets.confirm.acceptLabel / cancelLabel |
Solo puede haber un diálogo visible a la vez. Una nueva llamada cierra la sesión anterior (confirm pendiente resuelve false).
Tipos TypeScript exportados
Desde el entrypoint principal:
import {
useDialogMessage,
resolveDialogMessageMessages,
resolveExtensionLocale,
type DialogMessageApi,
type DialogMessageOptions,
type DialogMessageConfirmOptions,
type DialogMessageDefaults,
type DialogMessagePresetConfig,
type DialogMessagePresetsDefaults,
type DialogMessageFontDefaults,
type DialogMessageI18nMessages,
type PartialDialogMessageI18nMessages,
type DialogMessageButtonStyleConfig,
type DialogMessageButtonThemeStyle,
type DialogMessageButtonVariant,
type DialogMessageThemeColor,
type DialogMessageThemeColorValue,
type DialogMessageThemeMode,
type DialogMessageVariant,
type ExtensionLocale,
type ResolvedDialogMessageDefaults,
configureDialogMessageDefaults,
BUILTIN_DIALOG_MESSAGE_DEFAULTS,
DIALOG_MESSAGE_VARIANTS,
} from "@benjaminor-dev/quasar-app-extension-dialog-message";
| Tipo | Uso |
|---|---|
DialogMessageApi |
Retorno de useDialogMessage() |
ExtensionLocale |
"en" | "es" | "pt" — boot locale |
DialogMessageI18nMessages |
Forma de boot messages (labels + presets anidados) |
PartialDialogMessageI18nMessages |
Override parcial de boot messages |
DialogMessageOptions |
Argumento de success, info, warn, error |
DialogMessageConfirmOptions |
Argumento de confirm() |
DialogMessageDefaults |
Opciones de configureDialogMessageDefaults |
DialogMessagePresetConfig |
Campos de cada entrada en presets |
DialogMessagePresetsDefaults |
Mapa parcial presets |
DialogMessageFontDefaults |
{ family?, sizeTitle?, sizeText? } |
DialogMessageButtonStyleConfig |
{ light?, dark? } con estilos de botones |
DialogMessageButtonThemeStyle |
Colores/variantes de botones en un tema |
DialogMessageButtonVariant |
"flat" | "outline" | "unelevated" | "push" |
DialogMessageThemeColor |
{ light?, dark? } para colores por tema |
DialogMessageThemeColorValue |
string o DialogMessageThemeColor (iconColor) |
DialogMessageThemeMode |
"light" | "dark" |
DialogMessageVariant |
"success" | "info" | "warn" | "error" | "confirm" |
ResolvedDialogMessageDefaults |
Defaults mergeados (referencia / avanzado) |
También se exportan configureDialogMessage (alias), resolveDialogMessageMessages, resolveExtensionLocale, BUILTIN_DIALOG_MESSAGE_DEFAULTS y DIALOG_MESSAGE_API_KEY (clave provide del boot para integraciones avanzadas).
Entrypoints públicos
Lo que importas en tu código:
| Entrypoint | Propósito |
|---|---|
@benjaminor-dev/quasar-app-extension-dialog-message |
useDialogMessage, configureDialogMessageDefaults, helpers i18n (resolveDialogMessageMessages, resolveExtensionLocale), tipos y DIALOG_MESSAGE_VARIANTS |
Boot (boot/dialog) y estilos (main.css) los registra la extensión en quasar.config al instalar — no hace falta importarlos a mano en una instalación normal.
Troubleshooting
Veo títulos o botones en inglés y quiero español (o portugués)
Sin configurar Quasar, los presets built-in están en inglés. Elige una opción:
// quasar.config.ts — recomendado
framework: {
lang: "es",
},
// src/boot/bor/bor-dialog-message-defaults.ts — fijar solo el locale de Dialog Message
configureDialogMessageDefaults({ locale: "es" });
Boots o estilos no aparecen en quasar.config
En condiciones normales el install registra el defaults boot en boot: [] y el runner inyecta boot/dialog + CSS al compilar. Si falta el defaults boot:
npx quasar ext invoke @benjaminor-dev/dialog-message
Error: Pinia no inicializada
- Verifica un boot de Pinia en el host (
app.use(pinia)o equivalente). - En
quasar.config, el boot de Pinia debe ir antes que el bootdialogde esta extensión.
useDialogMessage() fuera de setup
Llámalo dentro de setup, otro composable o <script setup>. El boot debe haberse ejecutado (app montada).
El diálogo no muestra título
- Revisa si pasaste
title: ""(oculta el título a propósito). - Si omites
title, se usapresets.<variant>.titledel boot.
confirm() siempre resuelve false
- Comprueba que no llamas
hide()ni abres otro diálogo antes de pulsar un botón. - Una segunda llamada mientras el primero está abierto cierra el anterior con
false.
El diálogo queda detrás de otro overlay
Ajusta zIndex en boot (default 7000) según la jerarquía de capas de tu app.
Cambié presets en boot y no se refleja
Reinicia el dev server. Confirma que editas src/boot/bor/bor-dialog-message-defaults.ts del host, no solo la plantilla de la extensión.
MIT © Benjamín Olvera R.